Thứ hai, 22/04/2019 | 00:00 GMT+7

Cách cạo các trang web và đăng nội dung lên Twitter bằng Python 3

Các bot Twitter là một cách mạnh mẽ để quản lý mạng xã hội của bạn cũng như extract thông tin từ mạng tiểu blog. Bằng cách tận dụng các API linh hoạt của Twitter, bot có thể làm rất nhiều việc: tweet, tweet lại, “tweet yêu thích”, theo dõi những người có sở thích nhất định, trả lời tự động, v.v. Mặc dù mọi người có thể và làm, lạm dụng quyền của bot của họ, dẫn đến trải nghiệm tiêu cực cho user khác, nhưng nghiên cứu cho thấy rằng mọi người coi bot Twitter như một nguồn thông tin tin cậy . Ví dụ: một bot có thể thu hút những người theo dõi của bạn bằng nội dung ngay cả khi bạn không trực tuyến. Một số bot thậm chí còn cung cấp thông tin quan trọng và hữu ích, như @EarthquakesSF . Các ứng dụng cho bot là vô hạn. Tính đến năm 2019, ước tính rằng bot chiếm khoảng 24% tổng số tweet trên Twitter.

Trong hướng dẫn này, bạn sẽ xây dựng một bot Twitter bằng cách sử dụng thư viện API Twitter cho Python. Bạn sẽ sử dụng các khóa API từ account Twitter của bạn để ủy quyền cho bot của bạn và xây dựng khả năng thu thập nội dung từ hai trang web. Hơn nữa, bạn sẽ lập trình cho bot của bạn luân phiên tweet nội dung từ hai trang web này và vào những khoảng thời gian đã định. Lưu ý bạn sẽ sử dụng Python 3 trong hướng dẫn này.

Yêu cầu

Bạn cần những thứ sau để hoàn thành hướng dẫn này:

Lưu ý: Bạn sẽ cài đặt account nhà phát triển với Twitter, account này bao gồm việc Twitter xem xét ứng dụng trước khi bạn có thể truy cập các khóa API mà bạn yêu cầu cho bot này. Bước 1 xem qua các chi tiết cụ thể để hoàn thành đơn đăng ký.

Bước 1 - Cài đặt account nhà phát triển của bạn và truy cập khóa API Twitter của bạn

Trước khi bắt đầu mã hóa bot của bạn , bạn cần các khóa API để Twitter nhận ra các yêu cầu của bot của bạn. Trong bước này, bạn sẽ cài đặt Tài khoản nhà phát triển Twitter của bạn và truy cập các khóa API cho bot Twitter của bạn.

Để nhận các khóa API của bạn, hãy truy cập developer.twitter.com và đăng ký ứng dụng bot của bạn với Twitter bằng cách nhấp vào Áp dụng ở phần trên cùng bên phải của trang.

Bây giờ hãy nhấp vào Đăng ký account nhà phát triển .

Tiếp theo, nhấp vào Tiếp tục để liên kết tên user Twitter của bạn với ứng dụng bot mà bạn sẽ xây dựng trong hướng dẫn này.

Hiệp hội tên  user  Twitter với Bot

Trên trang tiếp theo, với mục đích của hướng dẫn này, bạn sẽ chọn tùy chọn Tôi đang yêu cầu quyền truy cập cho mục đích sử dụng cá nhân của riêng tôi vì bạn sẽ xây dựng một bot cho mục đích giáo dục cá nhân của bạn .

Sử dụng cá nhân API Twitter

Sau khi chọn Tên account Quốc gia của bạn , hãy chuyển sang phần tiếp theo. Bạn quan tâm đến (các) trường hợp sử dụng nào? , chọn tùy chọn Xuất bản và quản lý Tweetsdự án Sinh viên / Học cách viết mã .Các danh mục này là đại diện tốt nhất cho lý do bạn đang hoàn thành hướng dẫn này.

Mục đích của Twitter Bot

Sau đó, cung cấp mô tả về bot mà bạn đang cố gắng xây dựng. Twitter yêu cầu điều này để bảo vệ khỏi sự lạm dụng của bot; vào năm 2018, họ đã giới thiệu hiệu đính như vậy. Đối với hướng dẫn này, bạn sẽ tìm hiểu nội dung tập trung vào công nghệ từ The New StackThe Coursera Blog .

Khi quyết định nhập nội dung gì vào hộp mô tả , hãy lập mô hình câu trả lời của bạn trên các dòng sau cho mục đích của hướng dẫn này:

Tôi đang làm theo một hướng dẫn để xây dựng một bot Twitter có thể lấy nội dung từ các trang web như thenewstack.io (The New Stack) và blog.coursera.org (Blog của Coursera) và trích dẫn tweet từ chúng. Nội dung cóp nhặt sẽ được tổng hợp và sẽ được tweet theo kiểu vòng tròn thông qua các chức năng của trình tạo Python.

Cuối cùng, chọn không cho Sản phẩm, dịch vụ hoặc phân tích của bạn có cung cấp nội dung Twitter hoặc thông tin bắt nguồn cho một tổ chức chính phủ không?

Ý định của Twitter Bot

Tiếp theo, chấp nhận các điều khoản và điều kiện của Twitter, nhấp vào Gửi đơn đăng ký , sau đó xác minh địa chỉ email của bạn. Twitter sẽ gửi một email xác minh cho bạn sau khi bạn gửi biểu mẫu này.

Sau khi xác minh email của bạn , bạn sẽ nhận được một trang Ứng dụng đang được xem xét với biểu mẫu phản hồi cho quy trình đăng ký.

Bạn cũng sẽ nhận được một email khác từ Twitter về bài đánh giá:

Email Xem xét Đơn đăng ký

Dòng thời gian cho quá trình xét duyệt đơn đăng ký của Twitter có thể thay đổi đáng kể, nhưng thường thì Twitter sẽ xác nhận điều này trong vòng vài phút. Tuy nhiên, nếu quá trình xem xét đơn đăng ký của bạn mất nhiều thời gian hơn thời gian này, điều này không có gì lạ và bạn sẽ nhận được nó trong vòng một hoặc hai ngày. Sau khi bạn nhận được xác nhận, Twitter đã cho phép bạn tạo khóa của bạn . Bạn có thể truy cập những thứ này trong tab Key và mã thông báo sau khi nhấp vào nút chi tiết của ứng dụng trên developer.twitter.com/apps .

Cuối cùng, chuyển đến tab Quyền trên trang ứng dụng của bạn và đặt tùy chọn Quyền truy cập thành Đọc và Viết vì bạn cũng muốn viết nội dung tweet. Thông thường, bạn sẽ sử dụng chế độ chỉ đọc cho các mục đích nghiên cứu như phân tích xu hướng, khai thác dữ liệu, v.v. Tùy chọn cuối cùng cho phép user tích hợp chatbots vào các ứng dụng hiện có của họ, vì chatbots yêu cầu quyền truy cập vào tin nhắn trực tiếp.

Trang quyền ứng dụng Twitter

Bạn có quyền truy cập vào API mạnh mẽ của Twitter, đây sẽ là một phần quan trọng trong ứng dụng bot của bạn. Đến đây bạn sẽ cài đặt môi trường của bạn và bắt đầu xây dựng bot của bạn .

Bước 2 - Xây dựng những điều cần thiết

Trong bước này, bạn sẽ viết mã để xác thực bot của bạn với Twitter bằng cách sử dụng các khóa API và tạo tweet có lập trình đầu tiên qua tay cầm Twitter của bạn. Đây sẽ là một cột mốc quan trọng trong con đường của bạn hướng tới mục tiêu xây dựng một bot Twitter có chức năng quét nội dung từ The New StackBlog Coursera và tweet chúng theo định kỳ.

Đầu tiên, bạn sẽ cài đặt một folder dự án và một môi trường lập trình cụ thể cho dự án của bạn .

Tạo folder dự án của bạn:

  • mkdir bird

Di chuyển vào folder dự án của bạn:

  • cd bird

Sau đó, tạo một môi trường ảo Python mới cho dự án của bạn:

  • python3 -m venv bird-env

Sau đó, kích hoạt môi trường của bạn bằng lệnh sau:

  • source bird-env/bin/activate

Thao tác này sẽ đính kèm tiền tố (bird-env) vào dấu nhắc trong cửa sổ terminal của bạn.

Bây giờ, hãy chuyển sang editor của bạn và tạo một file có tên là credentials.py , file này sẽ lưu trữ các khóa API Twitter của bạn:

  • nano credentials.py

Thêm nội dung sau, thay thế mã được đánh dấu bằng các khóa của bạn từ Twitter:

bird / credentials.py
 ACCESS_TOKEN='your-access-token' ACCESS_SECRET='your-access-secret' CONSUMER_KEY='your-consumer-key' CONSUMER_SECRET='your-consumer-secret' 

Bây giờ, bạn sẽ cài đặt thư viện API chính để gửi yêu cầu đến Twitter. Đối với dự án này, bạn sẽ yêu cầu các thư viện sau: nltk , requests , twitter , lxml , randomtime . randomtime là một phần của thư viện chuẩn của Python, vì vậy bạn không cần phải cài đặt riêng các thư viện này. Để cài đặt các thư viện còn lại, bạn sẽ sử dụng pip , một trình quản lý gói cho Python.

Mở terminal của bạn, đảm bảo bạn đang ở trong folder dự án và chạy lệnh sau:

  • pip3 install lxml nltk requests twitter
  • lxmlrequests : Bạn sẽ sử dụng chúng để tìm kiếm trên web.
  • twitter : Đây là thư viện để thực hiện các cuộc gọi API đến server của Twitter.
  • nltk : (bộ công cụ ngôn ngữ tự nhiên) Bạn sẽ sử dụng để chia các đoạn blog thành các câu.
  • random : Bạn sẽ sử dụng điều này để chọn ngẫu nhiên các phần của toàn bộ bài đăng trên blog đã cóp nhặt.
  • time : Bạn sẽ sử dụng để đặt bot của bạn ngủ định kỳ sau một số hành động nhất định.

Khi bạn đã cài đặt các thư viện, bạn đã sẵn sàng để bắt đầu lập trình. Bây giờ, bạn sẽ nhập thông tin đăng nhập của bạn vào tập lệnh chính sẽ chạy bot. Cùng với credentials.py , từ editor của bạn, hãy tạo một file trong folder dự án bird và đặt tên là bot.py :

  • nano bot.py

Trên thực tế, bạn sẽ truyền bá chức năng của bot của bạn trên nhiều file khi nó ngày càng phát triển phức tạp hơn. Tuy nhiên, trong hướng dẫn này, bạn sẽ đặt tất cả mã của bạn trong một tập lệnh duy nhất, bot.py , cho mục đích demo .

Trước tiên, bạn sẽ kiểm tra các khóa API của bạn bằng cách ủy quyền cho bot của bạn. Bắt đầu bằng cách thêm đoạn mã sau vào bot.py :

bird / bot.py
import random import time  from lxml.html import fromstring import nltk nltk.download('punkt') import requests from twitter import OAuth, Twitter  import credentials 

Tại đây, bạn nhập các thư viện cần thiết; và trong một vài trường hợp, bạn nhập các chức năng cần thiết từ các thư viện. Bạn sẽ sử dụng hàm fromstring sau này trong mã để chuyển đổi nguồn chuỗi của một trang web có sẵn thành một cấu trúc cây để dễ dàng extract thông tin có liên quan từ trang hơn. OAuth sẽ giúp bạn xây dựng đối tượng xác thực từ các khóa của bạn và Twitter sẽ xây dựng đối tượng API chính cho tất cả các giao tiếp tiếp theo với server của Twitter.

Bây giờ hãy mở rộng bot.py bằng các dòng sau:

bird / bot.py
... tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')  oauth = OAuth(         credentials.ACCESS_TOKEN,         credentials.ACCESS_SECRET,         credentials.CONSUMER_KEY,         credentials.CONSUMER_SECRET     ) t = Twitter(auth=oauth) 

nltk.download('punkt') download tập dữ liệu cần thiết để phân tích cú pháp các đoạn văn và mã hóa (chia nhỏ) chúng thành các thành phần nhỏ hơn. tokenizer là đối tượng bạn sẽ sử dụng sau này trong mã để tách các đoạn văn được viết bằng tiếng Anh.

oauth là đối tượng xác thực được xây dựng bằng cách cung cấp lớp OAuth nhập với các khóa API của bạn. Bạn xác thực bot của bạn qua dòng t = Twitter(auth=oauth) . ACCESS_TOKENACCESS_SECRET giúp nhận dạng đơn đăng ký của bạn. Cuối cùng, CONSUMER_KEYCONSUMER_SECRET trợ giúp trong việc nhận dạng xử lý mà ứng dụng tương tác với Twitter. Bạn sẽ sử dụng đối tượng t này để truyền đạt yêu cầu của bạn tới Twitter.

Bây giờ hãy lưu file này và chạy nó trong terminal của bạn bằng lệnh sau:

  • python3 bot.py

Đầu ra của bạn sẽ trông giống như sau, nghĩa là ủy quyền của bạn đã thành công:

Output
[nltk_data] Downloading package punkt to /Users/binaryboy/nltk_data... [nltk_data] Package punkt is already up-to-date!

Nếu bạn gặp lỗi, hãy xác minh các khóa API đã lưu của bạn bằng các khóa trong tài khoản nhà phát triển Twitter của bạn và thử lại. Đồng thời đảm bảo các thư viện yêu cầu được cài đặt chính xác. Nếu không, hãy sử dụng lại pip3 để cài đặt chúng.

Đến đây bạn có thể thử viết một cái gì đó theo chương trình. Nhập lệnh tương tự trên terminal có cờ -i để mở trình thông dịch Python sau khi thực thi tập lệnh của bạn:

  • python3 -i bot.py

Tiếp theo, nhập thông tin sau để gửi một tweet qua account của bạn:

  • t.statuses.update(status="Just setting up my Twttr bot")

Bây giờ, hãy mở dòng thời gian Twitter của bạn trong một trình duyệt và bạn sẽ thấy một dòng tweet ở đầu dòng thời gian chứa nội dung bạn đã đăng.

Tweet có lập trình đầu tiên

Đóng trình thông dịch bằng lệnh quit() hoặc CTRL + D

Bot của bạn bây giờ có khả năng cơ bản để tweet. Để phát triển bot của bạn để tweet nội dung hữu ích, bạn sẽ kết hợp việc tìm kiếm web trong bước tiếp theo.

Bước 3 - Chỉnh sửa trang web cho nội dung Tweet của bạn

Để giới thiệu một số nội dung thú vị hơn vào dòng thời gian của bạn, bạn sẽ extract nội dung từ New StackCoursera Blog , sau đó đăng nội dung này lên Twitter dưới dạng tweet. Nói chung, để lấy dữ liệu thích hợp từ các trang web mục tiêu của bạn, bạn phải thử nghiệm với cấu trúc HTML của chúng. Mỗi tweet đến từ bot mà bạn sẽ xây dựng trong hướng dẫn này sẽ có một liên kết đến một bài đăng trên blog từ các trang web đã chọn, cùng với một trích dẫn ngẫu nhiên từ blog đó. Bạn sẽ thực hiện thủ tục này trong một hàm cụ thể để cắt nội dung từ Coursera, vì vậy bạn sẽ đặt tên cho nó là scrape_coursera() .

Đầu tiên hãy mở bot.py :

  • nano bot.py

Thêm hàm scrape_coursera() vào cuối file của bạn:

bird / bot.py
... t = Twitter(auth=oauth)   def scrape_coursera(): 

Để thu thập thông tin từ blog, trước tiên bạn sẽ yêu cầu trang web có liên quan từ server của Coursera. Đối với điều đó, bạn sẽ sử dụng hàm get() từ thư viện requests . get() nhận một URL và tìm nạp trang web tương ứng. Vì vậy, bạn sẽ chuyển blog.coursera.org làm đối số để get() . Nhưng bạn cũng cần cung cấp tiêu đề trong yêu cầu GET của bạn , điều này sẽ đảm bảo server của Coursera nhận ra bạn là khách hàng chính hãng. Thêm các dòng được đánh dấu sau vào scrape_coursera() của bạn để cung cấp tiêu đề:

bird / bot.py
def scrape_coursera():     HEADERS = {         'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)'                       ' AppleWebKit/537.36 (KHTML, like Gecko) Cafari/537.36'         } 

Tiêu đề này sẽ chứa thông tin liên quan đến một trình duyệt web xác định chạy trên một hệ điều hành cụ thể. Miễn là thông tin này (thường được gọi là Tác nhân người User-Agent ) tương ứng với trình duyệt web thực và hệ điều hành, thì thông tin tiêu đề có phù hợp với trình duyệt web thực và hệ điều hành trên máy tính của bạn hay không không quan trọng. Do đó tiêu đề này sẽ hoạt động tốt cho tất cả các hệ thống.

Khi bạn đã xác định các tiêu đề, hãy thêm các dòng được đánh dấu sau để thực hiện yêu cầu GET tới Coursera bằng cách chỉ định URL của trang web blog:

bird / bot.py
... def scrape_coursera():     HEADERS = {         'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)'                       ' AppleWebKit/537.36 (KHTML, like Gecko) Cafari/537.36'         }     r = requests.get('https://blog.coursera.org', headers=HEADERS)     tree = fromstring(r.content) 

Thao tác này sẽ tìm nạp trang web vào máy của bạn và lưu thông tin từ toàn bộ trang web trong biến r . Bạn có thể đánh giá mã nguồn HTML của trang web bằng cách sử dụng thuộc tính content của r . Do đó, giá trị của r.content giống như những gì bạn thấy khi kiểm tra trang web trong trình duyệt của bạn bằng cách nhấp chuột phải vào trang và chọn tùy chọn Kiểm tra phần tử .

Ở đây bạn cũng đã thêm hàm fromstring . Bạn có thể chuyển mã nguồn của trang web vào hàm fromstring được nhập từ thư viện lxml để xây dựng cấu trúc tree của trang web. Cấu trúc cây này sẽ cho phép bạn truy cập thuận tiện vào các phần khác nhau của trang web. Mã nguồn HTML có cấu trúc giống cây cụ thể; mọi phần tử được bao trong <html> và được lồng vào sau đó.

Bây giờ, hãy mở https://blog.coursera.org trong trình duyệt và kiểm tra nguồn HTML của nó bằng các công cụ dành cho nhà phát triển của trình duyệt. Nhấp chuột phải vào trang và chọn tùy chọn Kiểm tra phần tử . Bạn sẽ thấy một cửa sổ xuất hiện ở cuối trình duyệt, hiển thị một phần mã nguồn HTML của trang.

kiểm tra trình duyệt

Tiếp theo, nhấp chuột phải vào hình thu nhỏ của bất kỳ bài đăng blog hiển thị nào và sau đó kiểm tra nó. Nguồn HTML sẽ đánh dấu các dòng HTML liên quan nơi hình thu nhỏ blog đó được xác định. Bạn sẽ nhận thấy rằng tất cả các bài đăng trên blog trên trang này được xác định trong <div> với lớp "recent" :

blog-div

Do đó, trong mã của bạn, bạn sẽ sử dụng tất cả các phần tử div bài đăng blog thông qua XPath của chúng, đây là một cách thuận tiện để giải quyết các phần tử của một trang web.

Để làm như vậy, hãy mở rộng chức năng của bạn trong bot.py như sau:

bird / bot.py
... def scrape_coursera():     HEADERS = {         'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)'                       ' AppleWebKit/537.36 (KHTML, like Gecko) Cafari/537.36'                     }     r = requests.get('https://blog.coursera.org', headers=HEADERS)     tree = fromstring(r.content)     links = tree.xpath('//div[@class="recent"]//div[@class="title"]/a/@href')     print(links)  scrape_coursera() 

Ở đây, XPath (chuỗi được truyền tới tree.xpath() ) thông báo rằng bạn muốn các phần tử div từ toàn bộ nguồn trang web, của lớp "recent" . // tương ứng với việc tìm kiếm trên toàn bộ trang web, div yêu cầu hàm chỉ extract các phần tử div[@class="recent"] yêu cầu nó chỉ extract những phần tử div có giá trị thuộc tính class của chúng là "recent" .

Tuy nhiên, bản thân bạn không cần những yếu tố này, bạn chỉ cần các liên kết mà chúng trỏ đến, để bạn có thể truy cập các bài đăng trên blog cá nhân để tìm nội dung của chúng. Do đó, bạn extract tất cả các liên kết bằng cách sử dụng các giá trị của các thẻ liên kết href nằm trong các thẻ div trước đó của các bài đăng trên blog.

Để kiểm tra chương trình của bạn cho đến nay, bạn gọi hàm scrape_coursera() ở cuối bot.py

Lưu và thoát khỏi bot.py

Bây giờ hãy chạy bot.py bằng lệnh sau:

  • python3 bot.py

Trong kết quả của bạn, bạn sẽ thấy danh sách các URL như sau:

Output
['https://blog.coursera.org/career-stories-from-inside-coursera/', 'https://blog.coursera.org/unlock-the-power-of-data-with-python-university-of-michigan-offers-new-programming-specializations-on-coursera/', ...]

Sau khi xác minh kết quả, bạn có thể xóa hai dòng được đánh dấu cuối cùng khỏi tập lệnh bot.py :

bird / bot.py
... def scrape_coursera():     ...     tree = fromstring(r.content)     links = tree.xpath('//div[@class="recent"]//div[@class="title"]/a/@href')     ~~print(links)~~  ~~scrape_coursera()~~ 

Bây giờ hãy mở rộng hàm trong bot.py với dòng được đánh dấu sau để extract nội dung từ một bài đăng trên blog:

bird / bot.py
... def scrape_coursera():     ...     links = tree.xpath('//div[@class="recent"]//div[@class="title"]/a/@href')     for link in links:         r = requests.get(link, headers=HEADERS)         blog_tree = fromstring(r.content) 

Bạn lặp lại từng liên kết, tìm nạp bài đăng blog tương ứng, extract một câu ngẫu nhiên từ bài đăng, sau đó tweet câu này dưới dạng trích dẫn, cùng với URL tương ứng. Extract một câu ngẫu nhiên bao gồm ba phần:

  1. Lấy tất cả các đoạn trong bài đăng blog làm danh sách.
  2. Chọn ngẫu nhiên một đoạn văn từ danh sách các đoạn văn.
  3. Chọn một câu ngẫu nhiên từ đoạn này.

Bạn sẽ thực hiện các bước này cho mỗi bài đăng trên blog. Để tìm nạp một, bạn thực hiện yêu cầu GET cho liên kết của nó.

Đến đây bạn đã có quyền truy cập vào nội dung của blog, bạn sẽ giới thiệu đoạn mã thực hiện ba bước này để extract nội dung bạn muốn từ đó. Thêm tiện ích mở rộng sau vào chức năng cạo của bạn thực hiện ba bước:

bird / bot.py
... def scrape_coursera():     ...     for link in links:         r = requests.get(link, headers=HEADERS)         blog_tree = fromstring(r.content)         paras = blog_tree.xpath('//div[@class="entry-content"]/p')         paras_text = [para.text_content() for para in paras if para.text_content()]         para = random.choice(paras_text)         para_tokenized = tokenizer.tokenize(para)         for _ in range(10):             text = random.choice(para_tokenized)             if text and 60 < len(text) < 210:                 break 

Nếu bạn kiểm tra bài đăng trên blog bằng cách mở liên kết đầu tiên, bạn sẽ nhận thấy rằng tất cả các đoạn đều thuộc về thẻ diventry-content là lớp của nó. Do đó, bạn extract tất cả các đoạn văn dưới dạng danh sách với paras = blog_tree.xpath('//div[@class="entry-content"]/p') .

Các đoạn bao gồm Div

Các phần tử danh sách không phải là đoạn văn theo nghĩa đen ; chúng là các đối tượng Element . Để extract văn bản ra khỏi các đối tượng này, bạn sử dụng phương thức text_content() . Dòng này tuân theo mẫu thiết kế hiểu danh sách của Python, định nghĩa một tập hợp bằng cách sử dụng một vòng lặp thường được viết ra trong một dòng. Trong bot.py , bạn extract văn bản cho từng đối tượng phần tử đoạn và lưu trữ nó trong danh sách nếu văn bản không trống. Để chọn ngẫu nhiên một đoạn từ danh sách các đoạn này, bạn kết hợp module random .

Cuối cùng, bạn phải chọn ngẫu nhiên một câu từ đoạn văn này, câu này được lưu trong biến para . Đối với nhiệm vụ này, trước tiên bạn chia đoạn văn thành các câu. Một cách tiếp cận để thực hiện điều này là sử dụng phương thức split() của Python. Tuy nhiên, điều này có thể khó khăn vì một câu có thể được chia ở nhiều điểm ngắt. Do đó, để đơn giản hóa các việc phân tách của bạn, bạn tận dụng xử lý ngôn ngữ tự nhiên thông qua thư viện nltk . Đối tượng tokenizer mà bạn đã xác định trước đó trong hướng dẫn sẽ hữu ích cho mục đích này.

Đến đây bạn có một danh sách các câu, bạn gọi random.choice() để extract một câu ngẫu nhiên. Bạn muốn câu này là trích dẫn cho một tweet, vì vậy nó không được vượt quá 280 ký tự. Tuy nhiên, vì lý do thẩm mỹ, bạn sẽ chọn một câu không quá lớn cũng không quá nhỏ. Bạn chỉ định rằng câu tweet của bạn phải có độ dài từ 60 đến 210 ký tự. Câu random.choice() chọn có thể không đáp ứng tiêu chí này. Để xác định câu đúng, tập lệnh của bạn sẽ thực hiện mười lần thử, mỗi lần kiểm tra tiêu chí. Khi câu được chọn ngẫu nhiên đáp ứng tiêu chí của bạn, bạn có thể thoát khỏi vòng lặp.

Mặc dù xác suất khá thấp nhưng có thể không câu nào đáp ứng được điều kiện kích thước này trong vòng mười lần thử. Trong trường hợp này, bạn sẽ bỏ qua bài đăng trên blog tương ứng và chuyển sang bài tiếp theo.

Đến đây bạn có một câu để trích dẫn, bạn có thể tweet nó bằng liên kết tương ứng. Bạn có thể thực hiện việc này bằng cách tạo ra một chuỗi có chứa câu được chọn ngẫu nhiên cũng như liên kết blog tương ứng. Đoạn mã gọi scrape_coursera() này sau đó sẽ đăng chuỗi đã thu được lên Twitter thông qua API của Twitter.

Mở rộng chức năng của bạn như sau:

bird / bot.py
... def scrape_coursera():     ...     for link in links:         ...         para_tokenized = tokenizer.tokenize(para)         for _ in range(10):             text = random.choice(para)             if text and 60 < len(text) < 210:                 break         else:             yield None         yield '"%s" %s' % (text, link) 

Tập lệnh chỉ thực hiện câu lệnh else khi vòng lặp for trước đó không bị phá vỡ. Vì vậy, nó chỉ xảy ra khi vòng lặp không thể tìm thấy câu phù hợp với điều kiện kích thước của bạn. Trong trường hợp đó, bạn chỉ cần nhường None để mã gọi hàm này có thể xác định rằng không có gì để tweet. Sau đó nó sẽ chuyển sang gọi lại hàm và lấy nội dung cho liên kết blog tiếp theo. Nhưng nếu vòng lặp không bị phá vỡ nghĩa là hàm đã tìm thấy một câu thích hợp; script sẽ không thực thi câu lệnh else và hàm sẽ mang lại một chuỗi bao gồm câu cũng như liên kết blog, được phân tách bằng một khoảng trắng duy nhất.

Việc triển khai hàm scrape_coursera() gần như hoàn tất. Nếu bạn muốn tạo một chức năng tương tự để quét một trang web khác, bạn sẽ phải lặp lại một số mã đã viết để quét blog của Coursera. Để tránh viết lại và sao chép các phần của mã và đảm bảo tập lệnh của bot tuân theo nguyên tắc KHÔ (Không tự lặp lại), bạn sẽ xác định và tóm tắt các phần của mã mà bạn sẽ sử dụng lặp đi lặp lại cho bất kỳ hàm quét nào được viết một lát sau.

Dù trang web có chức năng gì, bạn sẽ phải chọn ngẫu nhiên một đoạn văn và sau đó chọn một câu ngẫu nhiên từ đoạn văn đã chọn này - bạn có thể extract các chức năng này trong các chức năng riêng biệt. Sau đó, bạn có thể chỉ cần gọi các hàm này từ các hàm cạp của bạn và đạt được kết quả mong muốn. Bạn cũng có thể xác định HEADERS ngoài scrape_coursera() chức năng để tất cả các chức năng scraper thể sử dụng nó. Do đó, trong đoạn mã tiếp theo, định nghĩa HEADERS phải đứng trước định nghĩa của hàm quét, để cuối cùng bạn có thể sử dụng nó cho các công cụ cạo khác:

bird / bot.py
... HEADERS = {     'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)'                   ' AppleWebKit/537.36 (KHTML, like Gecko) Cafari/537.36'     }   def scrape_coursera():     r = requests.get('https://blog.coursera.org', headers=HEADERS)     ... 

Đến đây bạn có thể định nghĩa hàm extract_paratext() để extract một đoạn văn ngẫu nhiên từ danh sách các đối tượng đoạn văn. Đoạn văn ngẫu nhiên sẽ chuyển đến hàm dưới dạng đối số paras và trả về dạng mã hóa của đoạn đã chọn mà bạn sẽ sử dụng sau này để extract câu:

bird / bot.py
... HEADERS = {         'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)'                       ' AppleWebKit/537.36 (KHTML, like Gecko) Cafari/537.36'         }  def extract_paratext(paras):     """Extracts text from <p> elements and returns a clean, tokenized random     paragraph."""      paras = [para.text_content() for para in paras if para.text_content()]     para = random.choice(paras)     return tokenizer.tokenize(para)   def scrape_coursera():     r = requests.get('https://blog.coursera.org', headers=HEADERS)     ... 

Tiếp theo, bạn sẽ xác định một hàm sẽ extract một câu ngẫu nhiên có độ dài phù hợp (từ 60 đến 210 ký tự) từ đoạn được mã hóa mà nó lấy làm đối số, bạn có thể đặt tên là para . Nếu một câu như vậy không được phát hiện sau mười lần thử, hàm sẽ trả về None thay thế. Thêm mã được đánh dấu sau để xác định hàm extract_text() :

bird / bot.py
...  def extract_paratext(paras):     ...     return tokenizer.tokenize(para)   def extract_text(para):     """Returns a sufficiently-large random text from a tokenized paragraph,     if such text exists. Otherwise, returns None."""      for _ in range(10):         text = random.choice(para)         if text and 60 < len(text) < 210:             return text      return None   def scrape_coursera():     r = requests.get('https://blog.coursera.org', headers=HEADERS)     ... 

Khi bạn đã xác định các hàm trợ giúp mới này, bạn có thể xác định lại hàm scrape_coursera() để trông như sau:

bird / bot.py
... def extract_paratext():     for _ in range(10):<^>         text = random.choice(para)     ...   def scrape_coursera():     """Scrapes content from the Coursera blog."""      url = 'https://blog.coursera.org'     r = requests.get(url, headers=HEADERS)     tree = fromstring(r.content)     links = tree.xpath('//div[@class="recent"]//div[@class="title"]/a/@href')      for link in links:         r = requests.get(link, headers=HEADERS)         blog_tree = fromstring(r.content)         paras = blog_tree.xpath('//div[@class="entry-content"]/p')         para = extract_paratext(paras)         text = extract_text(para)         if not text:             continue          yield '"%s" %s' % (text, link) 

Lưu và thoát khỏi bot.py

Ở đây bạn đang sử dụng yield thay vì return bởi vì, để lặp lại các liên kết, hàm quét sẽ cung cấp cho bạn từng chuỗi tweet theo thứ tự tuần tự. Điều này nghĩa là khi bạn thực hiện cuộc gọi đầu tiên đến sc scraper được định nghĩa là sc = scrape_coursera() , bạn sẽ nhận được chuỗi tweet tương ứng với liên kết đầu tiên trong danh sách các liên kết mà bạn đã tính toán trong hàm scraper. Nếu bạn chạy mã sau trong trình thông dịch, bạn sẽ nhận được string_1string_2 như được hiển thị bên dưới, nếu biến links trong scrape_coursera() chứa một danh sách giống như ["https://thenewstack.io/cloud-native-live-twistlocks-virtual-conference/", "https://blog.coursera.org/unlock-the-power-of-data-with-python-university-of-michigan-offers-new-programming-specializations-on-coursera/", ...] .

  • python3 -i bot.py

Khởi tạo máy cạp và gọi nó là sc :

>>> sc = scrape_coursera() 

Nó bây giờ là một máy phát điện; nó tạo hoặc loại bỏ nội dung có liên quan từ Coursera, từng nội dung một. Bạn có thể truy cập từng nội dung có sẵn bằng cách gọi next() qua sc tuần tự:

>>> string_1 = next(sc) >>> string_2 = next(sc) 

Đến đây bạn có thể print các chuỗi mà bạn đã xác định để hiển thị nội dung đã được cạo:

>>> print(string_1) "Other speakers include Priyanka Sharma, director of cloud native alliances at GitLab and Dan Kohn, executive director of the Cloud Native Computing Foundation." https://thenewstack.io/cloud-native-live-twistlocks-virtual-conference/ >>> >>> print(string_2) "You can learn how to use the power of Python for data analysis with a series of courses covering fundamental theory and project-based learning." https://blog.coursera.org/unlock-the-power-of-data-with-python-university-of-michigan-offers-new-programming-specializations-on-coursera/ >>> 

Nếu bạn sử dụng return thay vào đó, bạn sẽ không thể lấy từng chuỗi một và trong một chuỗi. Nếu bạn chỉ cần thay thế yield bằng return trong scrape_coursera() , bạn sẽ luôn nhận được chuỗi tương ứng với bài đăng blog đầu tiên, thay vì nhận chuỗi đầu tiên trong lần gọi đầu tiên, chuỗi thứ hai trong lần gọi thứ hai, v.v. Bạn có thể sửa đổi hàm để chỉ cần trả về danh sách tất cả các chuỗi tương ứng với tất cả các liên kết, nhưng điều đó tốn nhiều bộ nhớ hơn. Ngoài ra, loại chương trình này có khả năng thực hiện nhiều yêu cầu đến server của Coursera trong một khoảng thời gian ngắn nếu bạn muốn toàn bộ danh sách một cách nhanh chóng. Điều này có thể dẫn đến việc bot của bạn tạm thời bị cấm truy cập vào một trang web. Do đó, yield là sự phù hợp tốt nhất cho nhiều loại công việc cạo mủ, nơi bạn chỉ cần thông tin được thu thập từng lần một.

Bước 4 - Lược bỏ nội dung bổ sung

Trong bước này, bạn sẽ xây dựng một bộ quét cho thenewstack.io . Quá trình này tương tự như những gì bạn đã hoàn thành ở bước trước, vì vậy đây sẽ là một cái nhìn tổng quan.

Mở trang web trong trình duyệt của bạn và kiểm tra nguồn trang. Ở đây, bạn sẽ thấy rằng tất cả các phần blog đều là phần tử div của normalstory-box lớp normalstory-box .

Kiểm tra nguồn HTML của trang web The New Stack

Đến đây bạn sẽ tạo một hàm scrape_thenewstack() mới có tên scrape_thenewstack() và thực hiện một yêu cầu GET tới thenewstack.io từ bên trong nó. Tiếp theo, extract các liên kết đến các blog từ các phần tử này và sau đó lặp lại từng liên kết. Thêm mã sau để đạt được điều này:

bird / bot.py
... def scrape_coursera():     ...     yield '"%s" %s' % (text, link)   def scrape_thenewstack():     """Scrapes news from thenewstack.io"""      r = requests.get('https://thenewstack.io', verify=False)          tree = fromstring(r.content)         links = tree.xpath('//div[@class="normalstory-box"]/header/h2/a/@href')         for link in links: 

Bạn sử dụng cờ verify=False vì các trang web đôi khi có thể có certificate bảo mật đã hết hạn và bạn có thể truy cập chúng nếu không có dữ liệu nhạy cảm nào liên quan, như trường hợp ở đây. Các verify=False cờ kể requests.get phương pháp để không kiểm tra giấy chứng nhận và tiếp tục dữ liệu quyến rũ như thường lệ. Nếu không, phương pháp sẽ tạo ra một lỗi về certificate bảo mật đã hết hạn.

Đến đây bạn có thể extract các đoạn của blog tương ứng với từng liên kết và sử dụng hàm extract_paratext() mà bạn đã xây dựng ở bước trước để lấy ra một đoạn ngẫu nhiên từ danh sách các đoạn có sẵn. Cuối cùng, extract một câu ngẫu nhiên từ đoạn văn này bằng cách sử dụng hàm extract_text() , sau đó yield nó bằng liên kết blog tương ứng. Thêm mã được đánh dấu sau vào file của bạn để hoàn thành các việc này:

bird / bot.py
... def scrape_thenewstack():     ...     links = tree.xpath('//div[@class="normalstory-box"]/header/h2/a/@href')      for link in links:         r = requests.get(link, verify=False)         tree = fromstring(r.content)         paras = tree.xpath('//div[@class="post-content"]/p')         para = extract_paratext(paras)         text = extract_text(para)           if not text:             continue          yield '"%s" %s' % (text, link) 

Đến đây bạn có một ý tưởng về những gì một quá trình cạo thường bao gồm. Như vậy, bạn có thể xây dựng công cụ cạo tùy chỉnh của riêng mình, chẳng hạn như có thể cạo các hình ảnh trong các bài đăng blog thay vì trích dẫn ngẫu nhiên. Để làm được điều đó, bạn có thể tìm các <img> có liên quan. Khi bạn có đường dẫn phù hợp cho các thẻ, đóng role là mã nhận dạng của chúng, bạn có thể truy cập thông tin trong các thẻ bằng cách sử dụng tên của các thuộc tính tương ứng. Ví dụ: trong trường hợp cóp nhặt hình ảnh, bạn có thể truy cập các liên kết của hình ảnh bằng cách sử dụng thuộc tính src của chúng.

Đến đây, bạn đã xây dựng hai chức năng quét nội dung từ hai trang web khác nhau và bạn cũng đã xây dựng hai chức năng trợ giúp để sử dụng lại các chức năng phổ biến trên hai trình quét. Bây giờ bot của bạn đã biết cách tweet và tweet nội dung gì, bạn sẽ viết mã để tweet nội dung cóp nhặt.

Bước 5 - Đăng nội dung cóp nhặt

Trong bước này, bạn sẽ mở rộng bot để thu thập nội dung từ hai trang web và tweet nó qua account Twitter của bạn. Chính xác hơn, bạn muốn nó đăng nội dung từ hai trang web luân phiên nhau, và đều đặn mười phút, trong một khoảng thời gian không xác định. Do đó, bạn sẽ sử dụngvòng lặp while vô hạn để triển khai chức năng mong muốn. Bạn sẽ thực hiện điều này như một phần của hàm main() , hàm này sẽ triển khai quy trình cấp cao cốt lõi mà bạn cần bot của bạn tuân theo:

bird / bot.py
... def scrape_thenewstack():     ...     yield '"%s" %s' % (text, link)   def main():     """Encompasses the main loop of the bot."""     print('---Bot started---\n')     news_funcs = ['scrape_coursera', 'scrape_thenewstack']     news_iterators = []       for func in news_funcs:         news_iterators.append(globals()[func]())     while True:         for i, iterator in enumerate(news_iterators):             try:                 tweet = next(iterator)                 t.statuses.update(status=tweet)                 print(tweet, end='\n\n')                 time.sleep(600)               except StopIteration:                 news_iterators[i] = globals()[newsfuncs[i]]() 

Đầu tiên, bạn tạo một danh sách tên của các hàm cạo bạn đã xác định trước đó và gọi nó là news_funcs . Sau đó, bạn tạo một danh sách trống sẽ chứa các chức năng news_iterators thực tế và đặt tên danh sách đó là news_iterators . Sau đó, bạn điền nó bằng cách lướt qua từng tên trong danh sách news_funcs và thêm trình lặp tương ứng trong danh sách news_iterators . Bạn đang sử dụng hàm globals() hợp sẵn của Python. Điều này trả về một từ điển ánh xạ tên biến với các biến thực tế trong tập lệnh của bạn. Một trình lặp là những gì bạn nhận được khi gọi một hàm scraper: ví dụ: nếu bạn viết coursera_iterator = scrape_coursera() , thì coursera_iterator sẽ là một trình lặp mà bạn có thể gọi các lệnh next() . Mỗi next() gọi next() sẽ trả về một chuỗi chứa một trích dẫn và liên kết tương ứng của nó, chính xác như được định nghĩa trong câu lệnh yield của hàm scrape_coursera() . Mỗi next() gọi next() đi qua một lần lặp lại vòng lặp for trong hàm scrape_coursera() . Do đó, bạn chỉ có thể thực hiện càng nhiều lệnh gọi next() khi có các liên kết blog trong hàm scrape_coursera() . Khi con số đó vượt quá, ngoại lệ StopIteration sẽ được nâng lên.

Khi cả hai lặp cư news_iterators danh sách, chính while vòng lặp bắt đầu. Bên trong nó, bạn có một vòng lặp for đi qua từng trình vòng lặp và cố gắng lấy nội dung được tweet. Sau khi có được nội dung, bot của bạn sẽ tweet nội dung đó và sau đó sẽ ngủ trong mười phút. Nếu trình lặp không có thêm nội dung để cung cấp, một ngoại lệ StopIteration sẽ được đưa ra, trên đó bạn làm mới trình lặp đó bằng cách khởi tạo lại nó, để kiểm tra tính khả dụng của nội dung mới hơn trên trang web nguồn. Sau đó, bạn chuyển sang trình lặp tiếp theo, nếu có. Ngược lại, nếu việc thực thi đến cuối danh sách trình lặp, bạn khởi động lại từ đầu và tweet nội dung có sẵn tiếp theo. Điều này làm cho nội dung tweet bot của bạn xen kẽ từ hai trình trích dẫn bao lâu tùy thích.

Tất cả những gì còn lại bây giờ là thực hiện cuộc gọi đến hàm main() . Bạn thực hiện việc này khi tập lệnh được trình thông dịch Python gọi trực tiếp :

bird / bot.py
... def main():     print('---Bot started---\n')<^>     news_funcs = ['scrape_coursera', 'scrape_thenewstack']     ...  if __name__ == "__main__":       main() 

Sau đây là version hoàn chỉnh của tập lệnh bot.py Bạn cũng có thể xem script trên repository GitHub này .

bird / bot.py
 """Main bot script - bot.py For the DigitalOcean Tutorial. """   import random import time   from lxml.html import fromstring import nltk   nltk.download('punkt') import requests    from twitter import OAuth, Twitter   import credentials  tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')  oauth = OAuth(         credentials.ACCESS_TOKEN,         credentials.ACCESS_SECRET,         credentials.CONSUMER_KEY,         credentials.CONSUMER_SECRET     ) t = Twitter(auth=oauth)  HEADERS = {         'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5)'                       ' AppleWebKit/537.36 (KHTML, like Gecko) Cafari/537.36'         }   def extract_paratext(paras):     """Extracts text from <p> elements and returns a clean, tokenized random     paragraph."""      paras = [para.text_content() for para in paras if para.text_content()]     para = random.choice(paras)     return tokenizer.tokenize(para)   def extract_text(para):     """Returns a sufficiently-large random text from a tokenized paragraph,     if such text exists. Otherwise, returns None."""      for _ in range(10):         text = random.choice(para)         if text and 60 < len(text) < 210:             return text      return None   def scrape_coursera():     """Scrapes content from the Coursera blog."""     url = 'https://blog.coursera.org'     r = requests.get(url, headers=HEADERS)     tree = fromstring(r.content)     links = tree.xpath('//div[@class="recent"]//div[@class="title"]/a/@href')      for link in links:         r = requests.get(link, headers=HEADERS)         blog_tree = fromstring(r.content)         paras = blog_tree.xpath('//div[@class="entry-content"]/p')         para = extract_paratext(paras)           text = extract_text(para)           if not text:             continue          yield '"%s" %s' % (text, link)     def scrape_thenewstack():     """Scrapes news from thenewstack.io"""      r = requests.get('https://thenewstack.io', verify=False)      tree = fromstring(r.content)     links = tree.xpath('//div[@class="normalstory-box"]/header/h2/a/@href')      for link in links:         r = requests.get(link, verify=False)         tree = fromstring(r.content)         paras = tree.xpath('//div[@class="post-content"]/p')         para = extract_paratext(paras)         text = extract_text(para)           if not text:             continue          yield '"%s" %s' % (text, link)   def main():     """Encompasses the main loop of the bot."""     print('Bot started.')     news_funcs = ['scrape_coursera', 'scrape_thenewstack']     news_iterators = []       for func in news_funcs:         news_iterators.append(globals()[func]())     while True:         for i, iterator in enumerate(news_iterators):             try:                 tweet = next(iterator)                 t.statuses.update(status=tweet)                 print(tweet, end='\n')                 time.sleep(600)             except StopIteration:                 news_iterators[i] = globals()[newsfuncs[i]]()   if __name__ == "__main__":       main()  

Lưu và thoát khỏi bot.py

Sau đây là một thực thi mẫu của bot.py :

  • python3 bot.py

Bạn sẽ nhận được kết quả hiển thị nội dung mà bot của bạn đã thu thập, ở định dạng tương tự như sau:

Output
[nltk_data] Downloading package punkt to /Users/binaryboy/nltk_data... [nltk_data] Package punkt is already up-to-date! ---Bot started--- "Take the first step toward your career goals by building new skills." https://blog.coursera.org/career-stories-from-inside-coursera/ "Other speakers include Priyanka Sharma, director of cloud native alliances at GitLab and Dan Kohn, executive director of the Cloud Native Computing Foundation." https://thenewstack.io/cloud-native-live-twistlocks-virtual-conference/ "You can learn how to use the power of Python for data analysis with a series of courses covering fundamental theory and project-based learning." https://blog.coursera.org/unlock-the-power-of-data-with-python-university-of-michigan-offers-new-programming-specializations-on-coursera/ "“Real-user monitoring is really about trying to understand the underlying reasons, so you know, ‘who do I actually want to fly with?" https://thenewstack.io/how-raygun-co-founder-and-ceo-spun-gold-out-of-monitoring-agony/

Sau khi chạy bot mẫu, bạn sẽ thấy dòng thời gian đầy đủ các tweet có lập trình được bot đăng trên trang Twitter của bạn. Nó trông giống như sau :

Đã đăng Tweet có lập trình

Như bạn thấy , bot đang tweet các liên kết blog cóp nhặt với các trích dẫn ngẫu nhiên từ mỗi blog làm điểm nổi bật. Nguồn cấp dữ liệu này hiện là nguồn cấp thông tin với các tweet xen kẽ giữa các trích dẫn blog từ Coursera và thenewstack.io. Bạn đã xây dựng một bot tổng hợp nội dung từ web và đăng nó lên Twitter. Như vậy, bạn có thể mở rộng phạm vi của bot này theo ý muốn của bạn bằng cách thêm nhiều trình tìm kiếm hơn cho các trang web khác nhau và bot sẽ tweet nội dung đến từ tất cả các trình thu thập dữ liệu theo kiểu vòng tròn và trong repository ảng thời gian mong muốn của bạn.

Kết luận

Trong hướng dẫn này, bạn đã xây dựng một bot Twitter cơ bản bằng Python và extract một số nội dung từ web để bot của bạn đăng tweet. Có rất nhiều ý tưởng về bot để thử; bạn cũng có thể thực hiện các ý tưởng của riêng mình cho tiện ích của bot. Bạn có thể kết hợp các chức năng linh hoạt được cung cấp bởi API của Twitter và tạo ra thứ gì đó phức tạp hơn. Đối với version của bot Twitter phức tạp hơn, hãy xem chirps , một khung bot Twitter sử dụng một số khái niệm nâng cao như đa stream để khiến bot làm nhiều việc đồng thời. Ngoài ra còn có một số bot có ý tưởng thú vị, như nghe nhầm . Không có giới hạn nào về khả năng sáng tạo mà người ta có thể sử dụng khi xây dựng chương trình Twitter. Việc tìm kiếm các điểm cuối API phù hợp để sử dụng cho việc triển khai bot của bạn là điều cần thiết.

Cuối cùng, nghi thức bot hay (“botiquette”) là điều quan trọng cần ghi nhớ khi xây dựng bot tiếp theo của bạn. Ví dụ: nếu bot của bạn kết hợp tính năng đăng lại, hãy đặt tất cả văn bản của các tweet đi qua một bộ lọc để phát hiện ngôn ngữ lạm dụng trước khi đăng lại chúng. Bạn có thể triển khai các tính năng như vậy bằng cách sử dụng biểu thức chính quy và xử lý ngôn ngữ tự nhiên. Ngoài ra, trong khi tìm kiếm các nguồn để thu thập thông tin, hãy theo dõi đánh giá của bạn và tránh những nguồn phát tán thông tin sai lệch. Để đọc thêm về phép lịch sự, bạn có thể truy cập bài đăng trên blog này của Joe Mayo về chủ đề.


Tags:

Các tin liên quan

module Web tích hợp: Cách sử dụng KV Storage
2019-03-22
Cách thu thập thông tin một trang web với Scrapy và Python 3
2019-03-20
Cách cạo các trang web với Beautiful Soup và Python 3
2019-03-20
Cách sử dụng API Web trong Python 3
2019-03-20
Tạo ứng dụng web tiến bộ (PWA) với React
2019-03-02
Tụ điện: Chạy ứng dụng web trên thiết bị di động
2019-02-27
Cách gửi thông báo đẩy web từ ứng dụng Django
2018-10-24
Cách xây dựng ứng dụng web hiện đại để quản lý thông tin khách hàng với Django và React trên Ubuntu 18.04
2018-10-22
Cách cài đặt Django Web Framework trên Ubuntu 18.04
2018-08-06
Cách sử dụng Trình quản lý cảnh báo và Trình xuất hộp đen để giám sát web server của bạn trên Ubuntu 16.04
2018-05-11