Web cạo mạng nội bộ python

Trong bài đăng này, có thể được đọc như phần tiếp theo hướng dẫn của chúng tôi về cách quét web mà không bị chặn, chúng tôi sẽ đề cập đến hầu hết tất cả các công cụ để thực hiện quét web trong Python. Chúng tôi sẽ đi từ cơ bản đến nâng cao, đề cập đến ưu và nhược điểm của từng loại. Tất nhiên, chúng tôi sẽ không thể đề cập đến mọi khía cạnh của mọi công cụ mà chúng tôi thảo luận, nhưng bài đăng này sẽ cung cấp cho bạn ý tưởng hay về chức năng của từng công cụ và thời điểm sử dụng một công cụ.

Ghi chú. Khi tôi nói về Python trong bài đăng trên blog này, bạn nên cho rằng tôi nói về Python3

0. Nguyên tắc cơ bản về web

Internet rất phức tạp. có nhiều công nghệ và khái niệm cơ bản liên quan để xem một trang web đơn giản trong trình duyệt của bạn. Mục tiêu của bài viết này không phải là đi sâu vào chi tiết về từng khía cạnh đó, mà là cung cấp cho bạn những phần quan trọng nhất để trích xuất dữ liệu từ web bằng Python

Giao thức truyền tải siêu văn bản

Giao thức truyền tải siêu văn bản [HTTP] sử dụng mô hình máy khách/máy chủ. Máy khách HTTP [trình duyệt, chương trình Python của bạn, cURL, các thư viện như Yêu cầu. ] mở một kết nối và gửi một tin nhắn [“Tôi muốn xem trang đó. /product”] tới máy chủ HTTP [Nginx, Apache. ]. Sau đó, máy chủ trả lời bằng một phản hồi [ví dụ mã HTML] và đóng kết nối

HTTP được gọi là giao thức phi trạng thái vì mỗi giao dịch [yêu cầu/phản hồi] là độc lập. Ví dụ, FTP có trạng thái vì nó duy trì kết nối

Về cơ bản, khi bạn nhập địa chỉ trang web vào trình duyệt của mình, yêu cầu HTTP sẽ trông như thế này

GET /product/ HTTP/1.1
Host: example.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate, sdch, br
Connection: keep-alive
User-Agent: Mozilla/5.0 [Macintosh; Intel Mac OS X 12_3_1] AppleWebKit/537.36 [KHTML, like Gecko] Chrome/100.0.4896.127 Safari/537.36

Trong dòng đầu tiên của yêu cầu này, bạn có thể thấy như sau

  • Phương thức hoặc động từ HTTP. Trong trường hợp của chúng tôi là
    Price : 19.99$
    
    7, cho biết rằng chúng tôi muốn tìm nạp dữ liệu. Có khá nhiều phương thức HTTP khác có sẵn như [e. g. để tải lên dữ liệu] và danh sách đầy đủ có tại đây
  • Đường dẫn của tệp, thư mục hoặc đối tượng chúng tôi muốn tương tác với. Trong trường hợp ở đây, thư mục
    Price : 19.99$
    
    8 ngay bên dưới thư mục gốc
  • Phiên bản của giao thức HTTP. Trong hướng dẫn này, chúng tôi sẽ tập trung vào HTTP 1
  • Nhiều trường tiêu đề. Kết nối, Tác nhân người dùng. Dưới đây là danh sách đầy đủ các tiêu đề HTTP

Dưới đây là các trường tiêu đề quan trọng nhất

  • Chủ nhà. Tiêu đề này cho biết tên máy chủ mà bạn đang gửi yêu cầu. Tiêu đề này đặc biệt quan trọng đối với lưu trữ ảo dựa trên tên, đây là tiêu chuẩn trong thế giới lưu trữ ngày nay
  • Đại lý người dùng. Điều này chứa thông tin về khách hàng bắt nguồn yêu cầu, bao gồm cả hệ điều hành. Trong trường hợp này, đó là trình duyệt web của tôi [Chrome] trên macOS. Tiêu đề này rất quan trọng vì nó được sử dụng để thống kê [có bao nhiêu người dùng truy cập trang web của tôi trên thiết bị di động so với máy tính để bàn] hoặc để ngăn chặn vi phạm của bot. Vì các tiêu đề này được gửi bởi khách hàng nên chúng có thể được sửa đổi [“Giả mạo tiêu đề”]. Đây chính xác là những gì chúng tôi sẽ làm với công cụ dọn dẹp của mình - làm cho công cụ dọn dẹp của chúng tôi trông giống như một trình duyệt web thông thường
  • Chấp nhận. Đây là danh sách các loại MIME mà máy khách sẽ chấp nhận dưới dạng phản hồi từ máy chủ. Có rất nhiều loại nội dung và loại phụ khác nhau. văn bản/đơn giản, văn bản/html, hình ảnh/jpeg, ứng dụng/json
  • Bánh quy. Trường tiêu đề này chứa danh sách các cặp tên-giá trị [tên1=giá trị1;tên2=giá trị2]. Cookie là một cách để các trang web có thể lưu trữ dữ liệu trên máy của bạn. Điều này có thể đến một ngày hết hạn nhất định [cookie tiêu chuẩn] hoặc chỉ tạm thời cho đến khi bạn đóng trình duyệt của mình [cookie phiên]. Cookie được sử dụng cho một số mục đích khác nhau, từ thông tin xác thực, tùy chọn người dùng, cho đến những thứ bất chính hơn như theo dõi người dùng bằng mã định danh người dùng duy nhất, được cá nhân hóa. Tuy nhiên, chúng là một tính năng quan trọng của trình duyệt để xác thực được đề cập. Khi bạn gửi biểu mẫu đăng nhập, máy chủ sẽ xác minh thông tin đăng nhập của bạn và nếu bạn đã cung cấp thông tin đăng nhập hợp lệ, sẽ cấp cookie phiên xác định rõ ràng phiên người dùng cho tài khoản người dùng cụ thể của bạn. Trình duyệt của bạn sẽ nhận cookie đó và sẽ chuyển nó cùng với tất cả các yêu cầu tiếp theo
  • người giới thiệu. Tiêu đề liên kết giới thiệu [vui lòng lưu ý lỗi đánh máy] chứa URL mà URL thực tế đã được yêu cầu từ đó. Tiêu đề này rất quan trọng vì các trang web sử dụng tiêu đề này để thay đổi hành vi của họ dựa trên nơi người dùng đến. Ví dụ: nhiều trang web tin tức có đăng ký trả phí và chỉ cho phép bạn xem 10% bài đăng, nhưng nếu người dùng đến từ một trang tổng hợp tin tức như Reddit, họ sẽ cho phép bạn xem toàn bộ nội dung. Họ sử dụng người giới thiệu để kiểm tra điều này. Đôi khi chúng tôi sẽ phải giả mạo tiêu đề này để lấy nội dung mà chúng tôi muốn trích xuất

Và danh sách được tiếp tục. bạn có thể tìm thấy danh sách tiêu đề đầy đủ ở đây

Một máy chủ sẽ phản hồi với một cái gì đó như thế này

HTTP/1.1 200 OK
Server: nginx/1.4.6 [Ubuntu]
Content-Type: text/html; charset=utf-8
Content-Length: 3352




 ...[HTML CODE]

Ở dòng đầu tiên, chúng ta có một thông tin mới, mã HTTP

Price : 19.99$
9. Mã 200 có nghĩa là yêu cầu đã được xử lý đúng cách. Bạn có thể tìm thấy danh sách đầy đủ tất cả các mã có sẵn trên Wikipedia. Theo dòng trạng thái, bạn có các tiêu đề phản hồi, phục vụ cùng mục đích với các tiêu đề yêu cầu mà chúng ta vừa thảo luận. Sau tiêu đề phản hồi, bạn sẽ có một dòng trống, theo sau là dữ liệu thực được gửi cùng với phản hồi này

Sau khi trình duyệt của bạn nhận được phản hồi đó, trình duyệt sẽ phân tích mã HTML, tìm nạp tất cả nội dung được nhúng [tệp JavaScript và CSS, hình ảnh, video] và hiển thị kết quả vào cửa sổ chính

Chúng tôi sẽ xem xét các cách khác nhau để thực hiện các yêu cầu HTTP bằng Python và trích xuất dữ liệu chúng tôi muốn từ các phản hồi

1. Mở Socket thủ công và gửi yêu cầu HTTP

Ổ cắm

Cách cơ bản nhất để thực hiện yêu cầu HTTP trong Python là mở ổ cắm TCP và gửi yêu cầu HTTP theo cách thủ công

import socket

HOST = 'www.google.com'  # Server hostname or IP address
PORT = 80                # The standard port for HTTP is 80, for HTTPS it is 443

client_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]
server_address = [HOST, PORT]
client_socket.connect[server_address]

request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'
client_socket.sendall[request_header]

response = ''
while True:
    recv = client_socket.recv[1024]
    if not recv:
        break
    response += str[recv]

print[response]
client_socket.close[]

Bây giờ chúng ta có phản hồi HTTP, cách cơ bản nhất để trích xuất dữ liệu từ nó là sử dụng các biểu thức chính quy

Biểu thức chính quy

Biểu thức chính quy [hay còn gọi là biểu thức chính quy] là một công cụ cực kỳ linh hoạt để xử lý, phân tích cú pháp và xác thực văn bản tùy ý. Biểu thức chính quy về cơ bản là một chuỗi xác định mẫu tìm kiếm bằng cú pháp chuẩn. Ví dụ: bạn có thể nhanh chóng xác định tất cả các số điện thoại trên một trang web

Kết hợp với tìm kiếm và thay thế cổ điển, biểu thức chính quy cũng cho phép bạn thực hiện thay thế chuỗi trên chuỗi động theo cách tương đối đơn giản. Ví dụ đơn giản nhất, trong ngữ cảnh tìm kiếm trên web, có thể là thay thế các thẻ chữ hoa trong tài liệu HTML được định dạng kém bằng các đối tác chữ thường phù hợp

Bây giờ bạn có thể tự hỏi tại sao điều quan trọng là phải hiểu các biểu thức chính quy khi thực hiện quét web bằng Python. Đó là một câu hỏi công bằng và xét cho cùng, có nhiều mô-đun Python khác nhau để phân tích cú pháp HTML bằng bộ chọn XPath và CSS

Trong một thế giới ngữ nghĩa lý tưởng, dữ liệu có thể đọc được bằng máy dễ dàng và thông tin được nhúng bên trong các phần tử HTML có liên quan với các thuộc tính có ý nghĩa. Nhưng thế giới thực là lộn xộn. Bạn sẽ thường tìm thấy một lượng lớn văn bản bên trong phần tử

^Price\s*:\s*[\d+\.\d{2}]\$
0. Ví dụ: nếu bạn muốn trích xuất dữ liệu cụ thể bên trong một văn bản lớn [giá, ngày, tên. ], bạn sẽ phải sử dụng các biểu thức chính quy

Ghi chú. Đây là một trang web tuyệt vời để kiểm tra regex của bạn. https. //regex101. com/. Ngoài ra, đây là một blog tuyệt vời để tìm hiểu thêm về họ. Bài đăng này sẽ chỉ bao gồm một phần nhỏ những gì bạn có thể làm với regex

Biểu thức chính quy có thể hữu ích khi bạn có loại dữ liệu này

Price : 19.99$

Chúng tôi có thể chọn nút văn bản này bằng biểu thức XPath và sau đó sử dụng loại biểu thức chính quy này để trích xuất giá

^Price\s*:\s*[\d+\.\d{2}]\$

Nếu bạn chỉ có HTML, nó sẽ phức tạp hơn một chút, nhưng xét cho cùng thì không nhiều hơn thế. Bạn cũng có thể chỉ định trong biểu thức của mình thẻ và sau đó sử dụng nhóm chụp cho văn bản

import re

html_content = '

Price : 19.99$

'
m = re.match['

[.+]', html_content] if m: print[m.group[1]]

Như bạn có thể thấy, có thể thực hiện gửi yêu cầu HTTP theo cách thủ công bằng một ổ cắm và phân tích cú pháp phản hồi bằng biểu thức chính quy, nhưng nó phức tạp và có API cấp cao hơn có thể giúp tác vụ này dễ dàng hơn

2. urllib3 & LXML

từ chối trách nhiệm. Rất dễ bị lạc trong vũ trụ urllib trong Python. Thư viện chuẩn chứa urllib và urllib2 [và đôi khi là urllib3]. Trong Python3, urllib2 đã được chia thành nhiều mô-đun và urllib3 sẽ không sớm trở thành một phần của thư viện chuẩn. Tình huống khó hiểu này sẽ là chủ đề của một bài đăng trên blog khác. Trong phần này, tôi quyết định chỉ nói về urllib3 vì nó được sử dụng rộng rãi trong thế giới Python, bao gồm cả Pip và Requests

Urllib3 là gói cấp cao cho phép bạn thực hiện hầu hết mọi thứ bạn muốn với yêu cầu HTTP. Với urllib3, chúng tôi có thể làm những gì chúng tôi đã làm trong phần trước với ít dòng mã hơn

Price : 19.99$
0

Như bạn có thể thấy, điều này ngắn gọn hơn nhiều so với phiên bản ổ cắm. Không chỉ vậy, API rất đơn giản. Ngoài ra, bạn có thể dễ dàng thực hiện nhiều việc khác, như thêm tiêu đề HTTP, sử dụng proxy, gửi biểu mẫu

Ví dụ: nếu chúng tôi quyết định đặt một số tiêu đề và sử dụng proxy, chúng tôi sẽ chỉ phải thực hiện các bước sau [bạn có thể tìm hiểu thêm về máy chủ proxy tại bestproxyreviews. com]

Price : 19.99$
1

Nhìn thấy? . Tuy nhiên, có một số thứ mà urllib3 không xử lý dễ dàng. Ví dụ: nếu chúng tôi muốn thêm cookie, chúng tôi phải tự tạo các tiêu đề tương ứng và thêm chúng vào yêu cầu

Cũng có những thứ mà urllib3 có thể làm mà Yêu cầu không thể. ví dụ: tạo và quản lý nhóm và nhóm proxy, cũng như quản lý chiến lược thử lại

Nói một cách đơn giản, urllib3 nằm giữa Yêu cầu và Ổ cắm về mặt trừu tượng, mặc dù nó gần với Yêu cầu hơn Ổ cắm

Thành thật mà nói, nếu bạn định quét web bằng Python, có lẽ bạn sẽ không trực tiếp sử dụng urllib3, đặc biệt nếu đây là lần đầu tiên của bạn

Tiếp theo, để phân tích phản hồi, chúng ta sẽ sử dụng gói LXML và các biểu thức XPath

XPath

XPath là công nghệ sử dụng các biểu thức đường dẫn để chọn các nút hoặc tập hợp nút trong tài liệu XML [hoặc tài liệu HTML]. Nếu bạn đã quen với khái niệm bộ chọn CSS, thì bạn có thể hình dung nó giống như một cái gì đó tương đối giống nhau.

Cũng như Mô hình đối tượng tài liệu, XPath đã trở thành tiêu chuẩn của W3C từ năm 1999. Mặc dù bản thân XPath không phải là ngôn ngữ lập trình, nhưng nó cho phép bạn viết các biểu thức có thể truy cập trực tiếp vào một nút cụ thể hoặc một tập hợp nút cụ thể mà không cần phải duyệt qua toàn bộ cây HTML [hoặc cây XML]

Để trích xuất dữ liệu từ tài liệu HTML bằng XPath, chúng ta cần ba điều

  • một tài liệu HTML
  • một số biểu thức XPath
  • một công cụ XPath sẽ chạy các biểu thức đó

Để bắt đầu, chúng tôi sẽ sử dụng HTML mà chúng tôi nhận được từ urllib3. Và bây giờ chúng tôi muốn trích xuất tất cả các liên kết từ trang chủ Google. Vì vậy, chúng tôi sẽ sử dụng một biểu thức XPath đơn giản,

^Price\s*:\s*[\d+\.\d{2}]\$
1 và chúng tôi sẽ sử dụng LXML để chạy nó. LXML là thư viện xử lý XML và HTML nhanh và dễ sử dụng hỗ trợ XPath

Cài đặt

Price : 19.99$
3

Dưới đây là đoạn mã xuất hiện ngay sau đoạn mã trước

Price : 19.99$
4

Và đầu ra sẽ trông như thế này

HTTP/1.1 200 OK
Server: nginx/1.4.6 [Ubuntu]
Content-Type: text/html; charset=utf-8
Content-Length: 3352




 ...[HTML CODE]
0

Hãy nhớ rằng ví dụ này thực sự rất đơn giản và không cho bạn thấy XPath mạnh mẽ như thế nào [Lưu ý. chúng ta cũng có thể sử dụng

^Price\s*:\s*[\d+\.\d{2}]\$
2, để trỏ thẳng đến thuộc tính
^Price\s*:\s*[\d+\.\d{2}]\$
3]. Nếu bạn muốn tìm hiểu thêm về XPath, bạn có thể đọc phần giới thiệu hữu ích này. Tài liệu LXML cũng được viết tốt và là một điểm khởi đầu tốt

Biểu thức XPath, giống như biểu thức chính quy, rất mạnh mẽ và là một trong những cách nhanh nhất để trích xuất thông tin từ HTML. Và giống như các biểu thức thông thường, XPath có thể nhanh chóng trở nên lộn xộn, khó đọc và khó bảo trì

Nếu bạn muốn tìm hiểu thêm về XPath, đừng ngần ngại đọc bài đăng trên blog chuyên dụng của tôi về XPath được áp dụng cho quét web

toto

3. Yêu cầu và BeautifulSoup

yêu cầu

Yêu cầu là vua của các gói Python. Với hơn 11.000.000 lượt tải xuống, đây là gói được sử dụng rộng rãi nhất cho Python.  

Nếu bạn đang xây dựng trình quét web Python đầu tiên của mình, chúng tôi khuyên bạn nên bắt đầu với Yêu cầu và BeautifulSoup

Cài đặt

HTTP/1.1 200 OK
Server: nginx/1.4.6 [Ubuntu]
Content-Type: text/html; charset=utf-8
Content-Length: 3352




 ...[HTML CODE]
1

Đưa ra yêu cầu với - dự định chơi chữ - Yêu cầu thật dễ dàng

HTTP/1.1 200 OK
Server: nginx/1.4.6 [Ubuntu]
Content-Type: text/html; charset=utf-8
Content-Length: 3352




 ...[HTML CODE]
2

Với Requests, dễ dàng thực hiện các yêu cầu POST, xử lý cookie, truy vấn tham số. Bạn cũng có thể tải xuống hình ảnh với Yêu cầu

Trên trang sau, bạn sẽ học cách sử dụng Yêu cầu với proxy. Điều này gần như bắt buộc để quét web ở quy mô lớn

Xác thực tin tức Hacker

Giả sử bạn đang xây dựng một trình quét Python tự động gửi bài đăng trên blog của chúng tôi tới Hacker news hoặc bất kỳ diễn đàn nào khác, chẳng hạn như Buffer. Chúng tôi cần xác thực trên các trang web đó trước khi đăng liên kết của mình. Đó là những gì chúng ta sẽ làm với Yêu cầu và BeautifulSoup

Đây là biểu mẫu đăng nhập Hacker News và DOM được liên kết


Có ba thẻ

^Price\s*:\s*[\d+\.\d{2}]\$
4 với thuộc tính
^Price\s*:\s*[\d+\.\d{2}]\$
5 [các yếu tố đầu vào khác không được gửi] trên biểu mẫu này. Cái đầu tiên có một loại ẩn với tên "goto" và hai cái còn lại là tên người dùng và mật khẩu

Nếu bạn gửi biểu mẫu bên trong trình duyệt Chrome của mình, bạn sẽ thấy rằng có rất nhiều thứ đang diễn ra. chuyển hướng và cookie đang được đặt. Cookie này sẽ được Chrome gửi trong mỗi yêu cầu tiếp theo để máy chủ biết rằng bạn đã được xác thực

Làm điều này với Yêu cầu thật dễ dàng. Nó sẽ tự động xử lý các chuyển hướng cho chúng tôi và việc xử lý cookie có thể được thực hiện với đối tượng Phiên

ĐẹpSúp

Điều tiếp theo chúng ta sẽ cần là BeautifulSoup, đây là một thư viện Python sẽ giúp chúng ta phân tích cú pháp HTML do máy chủ trả về, để tìm hiểu xem chúng ta đã đăng nhập hay chưa

Cài đặt

HTTP/1.1 200 OK
Server: nginx/1.4.6 [Ubuntu]
Content-Type: text/html; charset=utf-8
Content-Length: 3352




 ...[HTML CODE]
3

Vì vậy, tất cả những gì chúng ta phải làm là ĐĂNG ba đầu vào này với thông tin xác thực của chúng ta tới điểm cuối /login và kiểm tra sự hiện diện của một phần tử chỉ được hiển thị sau khi đăng nhập

HTTP/1.1 200 OK
Server: nginx/1.4.6 [Ubuntu]
Content-Type: text/html; charset=utf-8
Content-Length: 3352




 ...[HTML CODE]
4

Thật tuyệt vời, chỉ với một vài dòng mã Python, chúng tôi đã đăng nhập được vào một trang web và kiểm tra xem đăng nhập có thành công hay không. Bây giờ, hãy chuyển sang thử thách tiếp theo. nhận tất cả các liên kết trên trang chủ

Nhân tiện, Hacker News cung cấp một API mạnh mẽ, vì vậy chúng tôi lấy ví dụ này làm ví dụ, nhưng bạn nên sử dụng API thay vì cạo nó

Điều đầu tiên chúng ta cần làm là kiểm tra trang chủ của Hacker News để hiểu cấu trúc và các lớp CSS khác nhau mà chúng ta sẽ phải chọn


Rõ ràng từ ảnh chụp màn hình, tất cả các bài đăng là một phần của thẻ

^Price\s*:\s*[\d+\.\d{2}]\$
6 với lớp
^Price\s*:\s*[\d+\.\d{2}]\$
7. Vì vậy, hãy đơn giản là tìm tất cả các thẻ này. Tuy nhiên, một lần nữa, chúng ta có thể làm điều đó với một dòng mã

HTTP/1.1 200 OK
Server: nginx/1.4.6 [Ubuntu]
Content-Type: text/html; charset=utf-8
Content-Length: 3352




 ...[HTML CODE]
5

Sau đó, đối với mỗi liên kết, chúng tôi sẽ trích xuất ID, tiêu đề, URL và xếp hạng của liên kết đó

HTTP/1.1 200 OK
Server: nginx/1.4.6 [Ubuntu]
Content-Type: text/html; charset=utf-8
Content-Length: 3352




 ...[HTML CODE]
6

Tuyệt vời, chỉ với một vài dòng mã Python, chúng tôi đã quản lý để tải trang Hacker News và nhận thông tin chi tiết về tất cả các bài đăng. Nhưng trên hành trình đến với dữ liệu lớn, chúng tôi không chỉ muốn in dữ liệu, chúng tôi thực sự muốn duy trì dữ liệu đó. Bây giờ, hãy cố gắng làm cho trình cạp Python của chúng ta mạnh mẽ hơn một chút

Lưu trữ dữ liệu của chúng tôi trong PostgreSQL

Chúng tôi đã chọn một cơ sở dữ liệu quan hệ tốt cho ví dụ của chúng tôi ở đây - PostgreSQL

Để bắt đầu, chúng ta sẽ cần một phiên bản cơ sở dữ liệu hoạt động. Kiểm tra www. postgresql. org/download cho cái đó, chọn gói thích hợp cho hệ điều hành của bạn và làm theo hướng dẫn cài đặt của nó. Khi bạn đã cài đặt PostgreSQL, bạn sẽ cần thiết lập cơ sở dữ liệu [hãy đặt tên là

^Price\s*:\s*[\d+\.\d{2}]\$
8] và thêm một bảng cho các liên kết Tin tức Hacker của chúng ta với nó [hãy đặt tên cho cơ sở dữ liệu đó là
^Price\s*:\s*[\d+\.\d{2}]\$
9] với lược đồ sau

HTTP/1.1 200 OK
Server: nginx/1.4.6 [Ubuntu]
Content-Type: text/html; charset=utf-8
Content-Length: 3352




 ...[HTML CODE]
7

💡 Để quản lý cơ sở dữ liệu, bạn có thể sử dụng ứng dụng khách dòng lệnh riêng của PostgreSQL hoặc một trong các giao diện UI có sẵn

Được rồi, cơ sở dữ liệu đã sẵn sàng và chúng ta có thể quay lại mã của mình

Điều đầu tiên, chúng tôi cần thứ gì đó cho phép chúng tôi nói chuyện với PostgreSQL và Psycopg là một thư viện thực sự tuyệt vời cho điều đó. Như mọi khi, bạn có thể nhanh chóng cài đặt nó bằng pip

HTTP/1.1 200 OK
Server: nginx/1.4.6 [Ubuntu]
Content-Type: text/html; charset=utf-8
Content-Length: 3352




 ...[HTML CODE]
8

Phần còn lại tương đối dễ dàng và đơn giản. Chúng ta chỉ cần có được kết nối

HTTP/1.1 200 OK
Server: nginx/1.4.6 [Ubuntu]
Content-Type: text/html; charset=utf-8
Content-Length: 3352




 ...[HTML CODE]
9

Kết nối đó sẽ cho phép chúng tôi lấy con trỏ cơ sở dữ liệu

import socket

HOST = 'www.google.com'  # Server hostname or IP address
PORT = 80                # The standard port for HTTP is 80, for HTTPS it is 443

client_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]
server_address = [HOST, PORT]
client_socket.connect[server_address]

request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'
client_socket.sendall[request_header]

response = ''
while True:
    recv = client_socket.recv[1024]
    if not recv:
        break
    response += str[recv]

print[response]
client_socket.close[]
0

Và khi chúng ta có con trỏ, chúng ta có thể sử dụng phương thức

import re

html_content = '

Price : 19.99$

'
m = re.match['

[.+]', html_content] if m: print[m.group[1]]

0, để thực sự chạy lệnh SQL của mình

import socket

HOST = 'www.google.com'  # Server hostname or IP address
PORT = 80                # The standard port for HTTP is 80, for HTTPS it is 443

client_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]
server_address = [HOST, PORT]
client_socket.connect[server_address]

request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'
client_socket.sendall[request_header]

response = ''
while True:
    recv = client_socket.recv[1024]
    if not recv:
        break
    response += str[recv]

print[response]
client_socket.close[]
1

Hoàn hảo, chúng tôi đã lưu trữ mọi thứ trong cơ sở dữ liệu của mình

Giữ ngựa của bạn, xin vui lòng. Đừng quên

import re

html_content = '

Price : 19.99$

'
m = re.match['

[.+]', html_content] if m: print[m.group[1]]

1 giao dịch cơ sở dữ liệu [ngầm] của bạn 😉. Thêm một
import re

html_content = '

Price : 19.99$

'
m = re.match['

[.+]', html_content] if m: print[m.group[1]]

2 [và một vài
import re

html_content = '

Price : 19.99$

'
m = re.match['

[.+]', html_content] if m: print[m.group[1]]

3] và chúng tôi thực sự sẵn sàng


Và đối với đêm chung kết, đây là mã hoàn chỉnh với logic cạo từ trước, lần này lưu trữ mọi thứ trong cơ sở dữ liệu

import socket

HOST = 'www.google.com'  # Server hostname or IP address
PORT = 80                # The standard port for HTTP is 80, for HTTPS it is 443

client_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]
server_address = [HOST, PORT]
client_socket.connect[server_address]

request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'
client_socket.sendall[request_header]

response = ''
while True:
    recv = client_socket.recv[1024]
    if not recv:
        break
    response += str[recv]

print[response]
client_socket.close[]
2

Tóm lược

Như bạn có thể thấy, Yêu cầu và BeautifulSoup là những thư viện tuyệt vời để trích xuất dữ liệu và tự động hóa các hành động khác nhau, chẳng hạn như đăng biểu mẫu. Nếu bạn muốn chạy các dự án quét web quy mô lớn, bạn vẫn có thể sử dụng Yêu cầu, nhưng bạn sẽ cần phải tự mình xử lý nhiều phần

💡 Bạn đã biết về Công cụ khai thác dữ liệu của ScrapingBee. Họ không chỉ cung cấp một môi trường không có mã hoàn chỉnh cho dự án của bạn mà còn dễ dàng mở rộng quy mô và xử lý tất cả các tính năng nâng cao, chẳng hạn như JavaScript và proxy round-robin, ngay lập tức. Hãy xem thử và 1.000 yêu cầu đầu tiên luôn thuộc về chúng tôi

Nếu bạn muốn tìm hiểu thêm về Python, BeautifulSoup, các yêu cầu POST và đặc biệt là bộ chọn CSS, tôi thực sự khuyên bạn nên tham khảo các bài viết sau

  • Hướng dẫn Soup đẹp mắt. Quét các trang web bằng Python
  • Làm cách nào để gửi POST với Yêu cầu Python?

Như thường lệ, tất nhiên có rất nhiều cơ hội để cải thiện

  • Tìm cách song song hóa mã của bạn để làm cho nó nhanh hơn
  • Xử lý lỗi
  • kết quả lọc
  • Điều chỉnh yêu cầu của bạn để bạn không làm quá tải máy chủ

May mắn thay cho chúng tôi, tồn tại các công cụ có thể xử lý những vấn đề đó cho chúng tôi

Grequest

Mặc dù gói Yêu cầu rất dễ sử dụng nhưng bạn có thể thấy gói này hơi chậm nếu bạn có hàng trăm trang cần quét. Ngoài hộp, nó sẽ chỉ cho phép bạn gửi các yêu cầu đồng bộ, nghĩa là nếu bạn có 25 URL cần quét, bạn sẽ phải thực hiện từng cái một

Vì vậy, nếu một trang mất mười giây để tìm nạp, thì sẽ mất hơn bốn phút để tìm nạp 25 trang đó

import socket

HOST = 'www.google.com'  # Server hostname or IP address
PORT = 80                # The standard port for HTTP is 80, for HTTPS it is 443

client_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]
server_address = [HOST, PORT]
client_socket.connect[server_address]

request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'
client_socket.sendall[request_header]

response = ''
while True:
    recv = client_socket.recv[1024]
    if not recv:
        break
    response += str[recv]

print[response]
client_socket.close[]
3

Cách dễ nhất để tăng tốc quá trình này là thực hiện nhiều cuộc gọi cùng một lúc. Điều này có nghĩa là thay vì gửi từng yêu cầu một cách tuần tự, bạn có thể gửi yêu cầu theo lô năm

Trong trường hợp đó, mỗi lô sẽ xử lý đồng thời 5 URL, nghĩa là bạn sẽ loại bỏ 5 URL trong 10 giây, thay vì 50 hoặc toàn bộ bộ 25 URL trong 50 giây thay vì 250. Không tệ để tiết kiệm thời gian 🥳

Thông thường, điều này được thực hiện bằng cách sử dụng song song dựa trên luồng. Mặc dù, như mọi khi, phân luồng có thể phức tạp, đặc biệt đối với người mới bắt đầu. May mắn thay, có một phiên bản của gói Yêu cầu thực hiện tất cả công việc khó khăn cho chúng tôi, GRequests. Nó dựa trên Yêu cầu, nhưng cũng kết hợp gevent, API Python không đồng bộ được sử dụng rộng rãi cho ứng dụng web. Thư viện này cho phép chúng tôi gửi nhiều yêu cầu cùng một lúc và một cách dễ dàng và thanh lịch

Để bắt đầu, hãy cài đặt GRequests

import socket

HOST = 'www.google.com'  # Server hostname or IP address
PORT = 80                # The standard port for HTTP is 80, for HTTPS it is 443

client_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]
server_address = [HOST, PORT]
client_socket.connect[server_address]

request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'
client_socket.sendall[request_header]

response = ''
while True:
    recv = client_socket.recv[1024]
    if not recv:
        break
    response += str[recv]

print[response]
client_socket.close[]
4

Bây giờ, đây là cách gửi 25 URL ban đầu của chúng tôi theo đợt 5

import socket

HOST = 'www.google.com'  # Server hostname or IP address
PORT = 80                # The standard port for HTTP is 80, for HTTPS it is 443

client_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]
server_address = [HOST, PORT]
client_socket.connect[server_address]

request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'
client_socket.sendall[request_header]

response = ''
while True:
    recv = client_socket.recv[1024]
    if not recv:
        break
    response += str[recv]

print[response]
client_socket.close[]
5

Và đó là nó. GRequests hoàn hảo cho các tập lệnh nhỏ nhưng ít lý tưởng hơn cho mã sản xuất hoặc quét web quy mô lớn. Để làm được điều đó, chúng tôi có Scrapy 👇

4. Khung thu thập thông tin web

phế liệu


Scrapy là một khung quét web và thu thập dữ liệu web mạnh mẽ của Python. Nó cung cấp nhiều tính năng để tải xuống các trang web một cách không đồng bộ, xử lý và duy trì nội dung của chúng theo nhiều cách khác nhau. Nó cung cấp hỗ trợ cho đa luồng, thu thập dữ liệu [quá trình đi từ liên kết này sang liên kết khác để tìm mọi URL trong trang web], sơ đồ trang web, v.v.

Scrapy cũng có một chế độ tương tác được gọi là Scrapy Shell. Với Scrapy Shell, bạn có thể kiểm tra mã cạo của mình một cách nhanh chóng và đảm bảo rằng tất cả các biểu thức XPath hoặc bộ chọn CSS của bạn đều hoạt động mà không gặp trục trặc. Nhược điểm của Scrapy là đường cong học tập dốc. Có rất nhiều điều để học hỏi

Để theo dõi ví dụ của chúng tôi về Hacker News, chúng tôi sẽ viết một Scrapy Spider quét 15 trang kết quả đầu tiên và lưu mọi thứ trong tệp CSV

Bạn có thể dễ dàng cài đặt Scrapy bằng pip

import socket

HOST = 'www.google.com'  # Server hostname or IP address
PORT = 80                # The standard port for HTTP is 80, for HTTPS it is 443

client_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]
server_address = [HOST, PORT]
client_socket.connect[server_address]

request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'
client_socket.sendall[request_header]

response = ''
while True:
    recv = client_socket.recv[1024]
    if not recv:
        break
    response += str[recv]

print[response]
client_socket.close[]
6

Sau đó, bạn có thể sử dụng Scrapy CLI để tạo mã soạn sẵn cho dự án của chúng tôi

import socket

HOST = 'www.google.com'  # Server hostname or IP address
PORT = 80                # The standard port for HTTP is 80, for HTTPS it is 443

client_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]
server_address = [HOST, PORT]
client_socket.connect[server_address]

request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'
client_socket.sendall[request_header]

response = ''
while True:
    recv = client_socket.recv[1024]
    if not recv:
        break
    response += str[recv]

print[response]
client_socket.close[]
7

Bên trong

import re

html_content = '

Price : 19.99$

'
m = re.match['

[.+]', html_content] if m: print[m.group[1]]

4, chúng tôi sẽ tạo một tệp Python mới bằng mã nhện của chúng tôi

import socket

HOST = 'www.google.com'  # Server hostname or IP address
PORT = 80                # The standard port for HTTP is 80, for HTTPS it is 443

client_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]
server_address = [HOST, PORT]
client_socket.connect[server_address]

request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'
client_socket.sendall[request_header]

response = ''
while True:
    recv = client_socket.recv[1024]
    if not recv:
        break
    response += str[recv]

print[response]
client_socket.close[]
8

Có rất nhiều quy ước trong Scrapy. Trước tiên, chúng tôi cung cấp tất cả các URL mong muốn trong

import re

html_content = '

Price : 19.99$

'
m = re.match['

[.+]', html_content] if m: print[m.group[1]]

5. Sau đó, Scrapy sẽ tìm nạp từng URL và gọi
import re

html_content = '

Price : 19.99$

'
m = re.match['

[.+]', html_content] if m: print[m.group[1]]

6 cho từng URL, nơi chúng tôi sẽ sử dụng mã tùy chỉnh của mình để phân tích cú pháp
import re

html_content = '

Price : 19.99$

'
m = re.match['

[.+]', html_content] if m: print[m.group[1]]

7

Sau đó, chúng tôi cần tinh chỉnh Scrapy một chút để con nhện của chúng tôi hoạt động tốt với trang web mục tiêu

import socket

HOST = 'www.google.com'  # Server hostname or IP address
PORT = 80                # The standard port for HTTP is 80, for HTTPS it is 443

client_socket = socket.socket[socket.AF_INET, socket.SOCK_STREAM]
server_address = [HOST, PORT]
client_socket.connect[server_address]

request_header = b'GET / HTTP/1.0\r\nHost: www.google.com\r\n\r\n'
client_socket.sendall[request_header]

response = ''
while True:
    recv = client_socket.recv[1024]
    if not recv:
        break
    response += str[recv]

print[response]
client_socket.close[]
9

Bạn nên luôn bật tính năng này. Dựa trên thời gian phản hồi, tính năng này sẽ tự động điều chỉnh tỷ lệ yêu cầu và số lượng chuỗi đồng thời và đảm bảo trình thu thập thông tin của bạn không tràn ngập trang web với các yêu cầu. Chúng tôi sẽ không muốn điều đó, phải không?

Bạn có thể chạy mã này với Scrapy CLI và với các định dạng đầu ra khác nhau [CSV, JSON, XML. ]

Price : 19.99$
0

Và đó là nó. Bây giờ bạn có tất cả các liên kết của mình trong một tệp JSON được định dạng đẹp mắt

Còn rất nhiều điều để nói về Scrapy này. Vì vậy, nếu bạn muốn tìm hiểu thêm, vui lòng xem bài đăng trên blog chuyên dụng của chúng tôi về quét web bằng Scrapy

PySpider

PySpider là một giải pháp thay thế cho Scrapy, mặc dù hơi lỗi thời. Bản phát hành cuối cùng của nó là từ năm 2018. Tuy nhiên, nó vẫn có liên quan vì nó thực hiện nhiều thứ mà Scrapy không xử lý được

Đầu tiên, PySpider hoạt động tốt với các trang JavaScript [cuộc gọi SPA và Ajax] vì nó đi kèm với PhantomJS, một thư viện duyệt không đầu. Trong Scrapy, bạn sẽ cần cài đặt phần mềm trung gian để thực hiện việc này. Trên hết, PySpider đi kèm với một giao diện người dùng đẹp giúp bạn dễ dàng theo dõi tất cả các công việc thu thập thông tin của mình

giao diện PySpider

Tuy nhiên, bạn vẫn có thể thích sử dụng Scrapy vì một số lý do

  • Tài liệu tốt hơn nhiều so với PySpider với hướng dẫn dễ hiểu
  • Hệ thống bộ đệm HTTP tích hợp có thể tăng tốc trình thu thập thông tin của bạn
  • Xác thực HTTP tự động
  • Hỗ trợ chuyển hướng 3XX, cũng như thẻ làm mới meta HTML

5. trình duyệt không đầu

Selen & Chrome

Scrapy rất tốt cho các tác vụ quét web quy mô lớn. Tuy nhiên, rất khó để xử lý các trang web sử dụng nhiều JavaScript được triển khai, e. g. , dưới dạng SPA [Ứng dụng một trang]. Scrapy không tự xử lý JavaScript và sẽ chỉ cung cấp cho bạn mã HTML tĩnh

Nói chung, việc loại bỏ các SPA có thể là một thách thức vì thường có rất nhiều lệnh gọi AJAX và kết nối WebSocket liên quan. Nếu hiệu suất là một vấn đề, hãy luôn kiểm tra chính xác mã JavaScript đang làm gì. Điều này có nghĩa là kiểm tra thủ công tất cả các lệnh gọi mạng bằng trình kiểm tra trình duyệt của bạn và sao chép các lệnh gọi AJAX có chứa dữ liệu thú vị

Tuy nhiên, thông thường, có quá nhiều lệnh gọi HTTP liên quan để lấy dữ liệu bạn muốn và việc hiển thị trang trong trình duyệt không đầu có thể dễ dàng hơn. Một trường hợp sử dụng tuyệt vời khác cho điều đó, đó là chụp ảnh màn hình của một trang và đây là những gì chúng tôi sẽ làm với trang chủ Hacker News [chúng tôi thích Hacker News, phải không?] và sự trợ giúp của Selenium

❓ Em không hiểu, khi nào thì nên dùng Selenium hay không?

Dưới đây là ba trường hợp phổ biến nhất khi bạn cần Selenium

  1. Bạn đang tìm kiếm thông tin xuất hiện vài giây sau khi trang web được tải trên trình duyệt
  2. Trang web bạn đang cố gắng cạo đang sử dụng rất nhiều JavaScript
  3. Trang web mà bạn đang cố gắng tìm kiếm có một số kiểm tra JavaScript để chặn ứng dụng khách HTTP "cổ điển"

Bạn có thể cài đặt gói Selenium bằng pip

Price : 19.99$
1

Bạn cũng sẽ cần ChromeDriver. Trên mac OS, bạn có thể sử dụng brew cho điều đó

Price : 19.99$
2

Sau đó, chúng ta chỉ cần nhập Webdriver từ gói Selenium, định cấu hình Chrome với headless=True, đặt kích thước cửa sổ [nếu không thì nó thực sự nhỏ], khởi động Chrome, tải trang và cuối cùng là có được ảnh chụp màn hình tuyệt đẹp của chúng ta

Price : 19.99$
3

Đúng, là những cư dân mạng tốt, tất nhiên chúng tôi cũng

import re

html_content = '

Price : 19.99$

'
m = re.match['

[.+]', html_content] if m: print[m.group[1]]

8 phiên bản WebDriver. Bây giờ, bạn sẽ nhận được một ảnh chụp màn hình đẹp của trang chủ


Đương nhiên, bạn có thể làm được nhiều điều hơn nữa với Selenium API và Chrome. Rốt cuộc, đó là một phiên bản trình duyệt toàn diện

  • Chạy JavaScript
  • điền vào biểu mẫu
  • Nhấp vào các yếu tố
  • Trích xuất các phần tử bằng bộ chọn CSS/biểu thức XPath

Selenium và Chrome ở chế độ không đầu là sự kết hợp cuối cùng để cạo bất cứ thứ gì bạn muốn. Bạn có thể tự động hóa mọi thứ mà bạn có thể làm với trình duyệt Chrome thông thường của mình

Hạn chế lớn là Chrome cần nhiều bộ nhớ/sức mạnh CPU. Với một số tinh chỉnh, bạn có thể giảm dung lượng bộ nhớ xuống còn 300-400mb trên mỗi phiên bản Chrome, nhưng bạn vẫn cần 1 lõi CPU cho mỗi phiên bản

Đừng ngần ngại xem bài viết chuyên sâu của chúng tôi về Selenium và Python

Nếu bạn cần chạy nhiều phiên bản đồng thời, điều này sẽ yêu cầu một máy có thiết lập phần cứng phù hợp và đủ bộ nhớ để phục vụ tất cả các phiên bản trình duyệt của bạn. Nếu bạn muốn một giải pháp nhẹ nhàng và thoải mái hơn, hãy xem nền tảng SaaS của trình thu thập thông tin trang web của ScrapingBee, nền tảng này thực hiện rất nhiều công việc nặng nhọc cho bạn

Trình duyệt Robo

RoboBrowser là một thư viện Python bao gồm các Yêu cầu và BeautifulSoup thành một gói duy nhất và dễ sử dụng, đồng thời cho phép bạn biên dịch các tập lệnh tùy chỉnh của riêng mình để kiểm soát quy trình duyệt web của RoboBrowser. Nó là một thư viện nhẹ, nhưng nó không phải là một trình duyệt không đầu và vẫn có những hạn chế tương tự đối với Yêu cầu và BeautifulSoup, chúng tôi đã thảo luận trước đó

Ví dụ: nếu bạn muốn đăng nhập vào Hacker-News, thay vì tạo yêu cầu theo cách thủ công với Yêu cầu, bạn có thể viết một tập lệnh sẽ điền vào biểu mẫu và nhấp vào nút đăng nhập

Price : 19.99$
4

Như bạn có thể thấy, mã được viết như thể bạn đang thực hiện tác vụ theo cách thủ công trong trình duyệt thực, mặc dù đó không phải là thư viện trình duyệt không đầu thực sự

RoboBrowser rất thú vị vì cách tiếp cận gọn nhẹ của nó cho phép bạn dễ dàng song song hóa nó trên máy tính của mình. Tuy nhiên, vì nó không sử dụng một trình duyệt thực nên nó sẽ không thể xử lý JavaScript như lệnh gọi AJAX hoặc Ứng dụng một trang

Thật không may, tài liệu của nó cũng nhẹ và tôi không khuyên dùng nó cho người mới hoặc những người chưa quen với BeautilfulSoup hoặc Requests API

6. Cạo dữ liệu Reddit

Đôi khi, bạn thậm chí không cần phải cạo dữ liệu bằng ứng dụng khách HTTP hoặc trình duyệt không đầu. Bạn có thể trực tiếp sử dụng API được cung cấp bởi trang web mục tiêu. Đó là những gì chúng tôi sẽ thử ngay bây giờ với API Reddit

Để truy cập API, chúng tôi sẽ sử dụng Praw, một gói Python tuyệt vời bao bọc API Reddit

Để cài đặt nó

Price : 19.99$
5

Sau đó, bạn sẽ cần lấy khóa API. Truy cập https. //www. reddit. com/prefs/ứng dụng

Cuộn xuống dưới cùng để tạo ứng dụng


Như đã nêu trong tài liệu của Praw, đảm bảo cung cấp

import re

html_content = '

Price : 19.99$

'
m = re.match['

[.+]', html_content] if m: print[m.group[1]]

9 là "URL chuyển hướng"

Sau khi nhấp vào

Price : 19.99$
00, màn hình có thông tin chi tiết và thông tin đăng nhập API sẽ tải. Bạn sẽ cần ID khách hàng, bí mật và tác nhân người dùng cho ví dụ của chúng tôi


Bây giờ chúng tôi sẽ lấy 1.000 bài đăng hàng đầu từ /r/Entrepreneur và xuất nó thành tệp CSV

Price : 19.99$
6

Như bạn có thể thấy, phần trích xuất thực tế chỉ là một dòng mã Python. Chạy

Price : 19.99$
01 trên
Price : 19.99$
02 và lưu trữ các bài đăng trong
Price : 19.99$
03 🎉

Có nhiều trường hợp sử dụng khác cho Praw. Bạn có thể làm tất cả những điều điên rồ, chẳng hạn như phân tích các sub reddit trong thời gian thực với các thư viện phân tích tình cảm, dự đoán $GME tiếp theo

Phần kết luận

Đây là bảng tóm tắt nhanh về mọi công nghệ mà chúng ta đã thảo luận trong bài đăng trên blog này. Xin vui lòng, đừng ngần ngại cho chúng tôi biết nếu bạn biết một số tài nguyên mà bạn cảm thấy thuộc về đây

Namesocketurlllib3requestsscrapyselenium Dễ sử dụng- - -+ ++ + ++ ++Tính linh hoạt+ + ++ + ++ ++ + ++ + +Tốc độ thực thi+ + ++ ++ ++ + ++Trường hợp sử dụng phổ biến*
* Simple application [in terms of HTTP needs]* Crawling an important list of websites
* Filtering, extracting and loading scraped data* JS rendering
* Scraping SPA
* Automated testing
* Programmatic screenshotLearn more* Official documentation
* Great tutorial 👍* Official documentation
* PIP usage of urllib3, very interesting* Official documentation
* Requests usage of urllib3* Official documentation - Scrapy overview* Official documentation
* Scraping SPA

Tôi hy vọng bạn thích bài đăng trên blog này. Đây là phần giới thiệu nhanh về các công cụ Python được sử dụng nhiều nhất để quét web. Trong các bài đăng tiếp theo, chúng ta sẽ tìm hiểu sâu hơn về tất cả các công cụ hoặc chủ đề, như bộ chọn XPath và CSS

Nếu bạn muốn tìm hiểu thêm về các ứng dụng khách HTTP trong Python, chúng tôi vừa phát hành hướng dẫn này về các ứng dụng khách HTTP Python tốt nhất

Chúc mừng cạo

Kevin Sahin

Kevin đã làm việc trong ngành quét web 10 năm trước khi đồng sáng lập ScrapingBee. Ông cũng là tác giả của Java Web Scraping Handbook.

Chủ Đề