Web cạo tải thêm nút python beautifulsoup

tiền đề. để sửa lỗi cuộn vô hạn, bạn sẽ cần xem xét cấu trúc html trang của mình. Các trang Html đều khác nhau, nhưng ý tưởng chung là giống nhau. bạn sẽ cần tìm phần tử cuối cùng được tải trên trang, sử dụng selen để cuộn xuống phần tử đó, sử dụng thời gian. sleep[] để đợi trang tải thêm nội dung, cuộn lại đến phần tử được tải cuối cùng và lặp lại. Cho đến cuối trang

Đây là một ví dụ

selenium = get_selenium[]                           selenium.get["your/url"]    
last_elem = '';
while True:
current_last_elem = "#my-div > ul > li:last-child"
scroll = "document.querySelector[\'" + current_last_elem + "\'].scrollIntoView[];"
selenium.execute_script[scroll] # execute the js scroll
time.sleep[3] # wait for page to load new content
if [last_elem == current_elem]
break
else
last_elem = current_elem

Ở đây chúng tôi đang sử dụng jquery và javascript bên trong python.
Khá thú vị.

. selenium.get[] opens your url page.
Nếu bạn cần thêm từ khóa vào tìm kiếm url của mình, bạn có thể thực hiện

def get_selenium[]:                           
options = webdriver.ChromeOptions[]
options.add_argument['--ignore-certificate-errors']
options.add_argument['--incognito']
options.add_argument['headless']
driver = webdriver.Chrome[chrome_options=options]
return [driver]
3.

Chúng tôi khởi tạo last_elem thành 0

Chúng tôi nhận được current_last_elem với sự trợ giúp của CCS_selector hoặc Xpath. Để lấy đường dẫn, hãy mở trang của bạn, sử dụng công cụ webdev để chọn phần tử bạn cần đường dẫn đến [công cụ webdev thường mở bằng cách nhấn F12 hoặc google cách], chọn phần tử trong cấu trúc html của trang rồi nhấp chuột phải > Sao chép . Đây là một hướng dẫn

Chúng tôi sử dụng jquery và

def get_selenium[]:                           
options = webdriver.ChromeOptions[]
options.add_argument['--ignore-certificate-errors']
options.add_argument['--incognito']
options.add_argument['headless']
driver = webdriver.Chrome[chrome_options=options]
return [driver]
4 để cuộn trang xuống phần tử đã chọn. Hãy chú ý đến tất cả các dấu ngoặc đơn và dấu ngoặc kép bạn cần ở đây để định dạng chính xác và cả các ký tự thoát nữa, tôi. e.
def get_selenium[]:                           
options = webdriver.ChromeOptions[]
options.add_argument['--ignore-certificate-errors']
options.add_argument['--incognito']
options.add_argument['headless']
driver = webdriver.Chrome[chrome_options=options]
return [driver]
5

Chúng tôi chạy tập lệnh js với

def get_selenium[]:                           
options = webdriver.ChromeOptions[]
options.add_argument['--ignore-certificate-errors']
options.add_argument['--incognito']
options.add_argument['headless']
driver = webdriver.Chrome[chrome_options=options]
return [driver]
0

.

def get_selenium[]:                           
options = webdriver.ChromeOptions[]
options.add_argument['--ignore-certificate-errors']
options.add_argument['--incognito']
options.add_argument['headless']
driver = webdriver.Chrome[chrome_options=options]
return [driver]
1 is important.
Nếu bạn không cho trang đủ thời gian để tải, trang sẽ không tìm thấy phần tử cuối cùng, bạn sẽ nhận được
def get_selenium[]:                           
options = webdriver.ChromeOptions[]
options.add_argument['--ignore-certificate-errors']
options.add_argument['--incognito']
options.add_argument['headless']
driver = webdriver.Chrome[chrome_options=options]
return [driver]
2 và trang sẽ ngừng cuộn.

. Every time we scroll, we check if a new last element is found.
Nếu có, nghĩa là chúng ta chưa đến cuối trang và chúng ta có thể tiếp tục cuộn.
Nếu không, trang đã cuộn xuống xong và chúng ta có thể thoát ra khỏi vòng lặp.

4 — CÁC VẤN ĐỀ THƯỜNG GẶP và cách khắc phục

Việc tìm đúng xpath tới phần tử cuối cùng sẽ mất chút thời gian.
Hãy kiên nhẫn và kiểm tra hai hoặc ba lần dấu ngoặc đơn và dấu ngoặc kép của bạn trong tập lệnh js.

Nếu bạn chắc chắn rằng đường dẫn là chính xác nhưng bạn vẫn nhận được phần tử cuối cùng không xác định hoặc luôn giống nhau, hãy thử tăng thời gian. ngủ[]. Trang có thể không có thời gian để tải hoàn toàn

Nếu mọi thứ có vẻ đúng nhưng nó vẫn không hoạt động, hãy nhận xét tùy chọn không đầu trong get_selenium[] để xem điều gì đang xảy ra bên trong

Xử lý phân trang trong quét web có thể là một thách thức khi xây dựng một công cụ quét web. Mặc dù việc triển khai phân trang có thể khác nhau rất nhiều, nhưng về cơ bản, chúng được chia thành bốn loại chính. Bài viết này sẽ đề cập đến các ví dụ thực tế, cùng với code trong Python để xử lý phân trang

Trước khi hiểu cách xử lý phân trang trong quét web, điều quan trọng là phải hiểu phân trang là gì trong phát triển web

Hầu hết các trang web chứa một lượng lớn dữ liệu. Không thể hiển thị tất cả dữ liệu trên một trang. Ngay cả khi đó là một tập dữ liệu nhỏ, nếu tất cả các bản ghi được hiển thị trên một trang, kích thước trang sẽ trở nên rất lớn. Một trang như vậy mất nhiều thời gian hơn để tải và tiêu tốn nhiều bộ nhớ hơn trong trình duyệt. Giải pháp là hiển thị các bản ghi hạn chế trên mỗi trang và cung cấp quyền truy cập vào các bản ghi còn lại bằng cách sử dụng phân trang.  

Trong trường hợp phân trang trong thiết kế web, một thành phần giao diện người dùng, thường được gọi là máy nhắn tin, được đặt ở cuối trang. Máy nhắn tin này có thể chứa các liên kết hoặc nút để di chuyển trang tiếp theo, trang trước, trang cuối cùng, trang đầu tiên hoặc một trang cụ thể. Việc triển khai thực tế thay đổi theo từng trang web.  

Mặc dù mỗi trang web có cách sử dụng phân trang, nhưng hầu hết các triển khai phân trang này đều thuộc một trong bốn loại sau

  • Với nút Tiếp theo

  • Số trang không có nút Tiếp theo

  • Phân trang với cuộn vô hạn

  • Phân trang với Load More

Trong bài viết này, chúng tôi sẽ kiểm tra các tình huống này trong khi cạo dữ liệu web

Hãy bắt đầu với một ví dụ đơn giản. Truy cập trang web Books to Scrape. Cuộn xuống cuối trang và chú ý phân trang

Trang web này có nút Tiếp theo. Nếu nút này được nhấp, trình duyệt sẽ tải trang tiếp theo

Lưu ý rằng bây giờ trang web này hiển thị nút trước đó cùng với nút Tiếp theo. Nếu chúng tôi tiếp tục nhấp vào Tiếp theo cho đến khi đến trang cuối cùng, đây là giao diện

Hơn nữa, với mỗi lần nhấp, URL sẽ thay đổi

  • Trang 1 – http. //sách. để cạo. com/catalogue/category/books/fantasy_19/index. html

  • Trang 2 – http. //sách. để cạo. com/catalogue/category/books/fantasy_19/page-2. html

  • Trang 3 – http. //sách. để cạo. com/catalogue/category/books/fantasy_19/page-3. html

Bước tiếp theo là kiểm tra đánh dấu HTML của liên kết tiếp theo. Điều này có thể được thực hiện bằng cách nhấn F12 hoặc Ctrl+Alt+I hoặc bằng cách nhấp chuột phải vào liên kết Tiếp theo và chọn Kiểm tra

Trong cửa sổ Kiểm tra, có thể thấy rằng nút Tiếp theo là một phần tử neo và chúng ta có thể tìm thấy URL của trang tiếp theo bằng cách tìm kiếm nó

Mã Python để xử lý phân trang

Hãy bắt đầu với việc viết một trình quét web cơ bản.  

Đầu tiên, chuẩn bị môi trường của bạn với các gói cần thiết. Mở terminal, kích hoạt môi trường ảo [tùy chọn] và thực hiện lệnh này để cài đặt các yêu cầu, beautifulsoup4 và lxml. Các yêu cầu sẽ được sử dụng cho các yêu cầu HTTP, beautifulsoup4 sẽ được sử dụng để định vị nút Tiếp theo trong HTML trong khi lxml là back-end cho beautifulsoup4

pip install requests beautifulsoup4 lxml

Bắt đầu với việc viết một đoạn mã đơn giản để tìm nạp trang đầu tiên và in phần cuối trang. Lưu ý rằng chúng tôi đang in chân trang để chúng tôi có thể theo dõi trang đang được phân tích cú pháp. Trong một ứng dụng trong thế giới thực, bạn sẽ thay thế nó bằng một giải pháp theo dõi và ghi nhật ký phù hợp hoặc từ bỏ khả năng hiển thị vì lý do hiệu suất

"""Handling pages with the Next button"""
import requests
from bs4 import BeautifulSoup

url = '//books.toscrape.com/catalogue/category/books/fantasy_19/index.html'

response = requests.get[url]
soup = BeautifulSoup[response.text, "lxml"]
footer_element = soup.select_one['li.current']
print[footer_element.text.strip[]]

Đầu ra của mã này sẽ chỉ đơn giản là phần chân trang của trang đầu tiên

Vài điểm cần lưu ý ở đây như sau

  • thư viện yêu cầu đang gửi yêu cầu GET tới URL đã chỉ định;

  • Đối tượng soup đang được truy vấn bằng CSS Selector. Bộ chọn CSS này dành riêng cho trang web

Hãy sửa đổi mã này để xác định vị trí nút Tiếp theo

next_page_element = soup.select_one['li.next > a']

Nếu tìm thấy next_page_element, chúng ta có thể lấy giá trị của thuộc tính href, chứa URL của trang tiếp theo. Một điều quan trọng cần lưu ý ở đây là thường thì href sẽ là một url tương đối. Trong những trường hợp như vậy, người ta có thể sử dụng phương thức urljoin từ urllib. mô-đun phân tích cú pháp để biến URL thành một URL tuyệt đối.  

Bằng cách gói mã quét một trang bằng một vòng lặp while và điều kiện kết thúc là không còn trang nào nữa, chúng tôi có thể truy cập tất cả các trang được liên kết đến bằng cách phân trang.  

"""Handling pages with the Next button"""
from urllib.parse import urljoin

import requests
from bs4 import BeautifulSoup

url = '//books.toscrape.com/catalogue/category/books/fantasy_19/index.html'

while True:
    response = requests.get[url]
    soup = BeautifulSoup[response.text, "lxml"]

    footer_element = soup.select_one['li.current']
    print[footer_element.text.strip[]]
    # Do more with each page.

    # Find the next page to scrape in the pagination.
    next_page_element = soup.select_one['li.next > a']
    if next_page_element:
        next_page_url = next_page_element.get['href']
        url = urljoin[url, next_page_url]
    else:
        break

Đầu ra của mã này sẽ là chân trang của cả ba trang

Một số trang web sẽ không hiển thị nút Tiếp theo mà chỉ hiển thị số trang. Ví dụ: đây là một ví dụ về phân trang từ https. //www. gosc. pl/doc/791526. Zaloz-zbroje

Nếu chúng tôi kiểm tra đánh dấu HTML cho trang này, có thể thấy một điều thú vị

________số 8

HTML chứa các liên kết đến tất cả các trang sau. Điều này làm cho việc truy cập tất cả các trang này trở nên dễ dàng. Bước đầu tiên là đến trang đầu tiên. Tiếp theo, chúng ta có thể sử dụng BeautifulSoup để trích xuất tất cả các liên kết này đến các trang khác. Cuối cùng, chúng ta có thể viết một vòng lặp for loại bỏ tất cả các liên kết này

"""Handling pages without the Next button"""
from urllib.parse import urljoin

import requests
from bs4 import BeautifulSoup

# Get the first page.
url = '//www.gosc.pl/doc/791526.Zaloz-zbroje'
response = requests.get[url]
soup = BeautifulSoup[response.text, 'lxml']
page_link_el = soup.select['.pgr_nrs a']
# Do more with the first page.

# Make links for and process the following pages.
for link_el in page_link_el:
    link = urljoin[url, link_el.get['href']]
    response = requests.get[link]
    soup = BeautifulSoup[response.text, 'lxml']
    print[response.url]
    # Do more with each page.

Kiểu phân trang này không hiển thị số trang hoặc nút tiếp theo.  

Hãy lấy trang web Quotes to Scrape làm ví dụ. Trang web này hiển thị một số trích dẫn hạn chế khi tải trang. Khi bạn cuộn xuống, nó sẽ tự động tải thêm các mục, số lượng có hạn tại một thời điểm. Một điều quan trọng khác cần lưu ý ở đây là URL không thay đổi khi nhiều trang được tải hơn.  

Trong những trường hợp như vậy, các trang web sử dụng lệnh gọi không đồng bộ tới API để nhận thêm nội dung và hiển thị nội dung này trên trang bằng JavaScript. Dữ liệu thực tế do API trả về có thể là HTML hoặc JSON

Xử lý các trang web có phản hồi JSON

Trước khi bạn tải trang web, hãy nhấn F12 để mở Công cụ dành cho nhà phát triển, chuyển đến tab Mạng và chọn XHR. Bây giờ hãy truy cập http. //dấu ngoặc kép. để cạo. com/scroll và theo dõi lưu lượng truy cập. Cuộn xuống để tải thêm nội dung.  

Bạn sẽ nhận thấy rằng khi bạn cuộn xuống, sẽ có nhiều yêu cầu hơn được gửi đến dấu ngoặc kép?page=x, trong đó x là số trang

Vì số lượng trang không được biết trước, người ta phải tìm ra thời điểm ngừng cạo. Đây là nơi has_next trong phản hồi từ dấu ngoặc kép?page=x sẽ hữu ích

Chúng ta có thể viết một vòng lặp while như đã làm ở phần trước. Lần này, không cần BeautifulSoup vì phản hồi là JSON và chúng ta có thể phân tích cú pháp trực tiếp bằng json. Sau đây là mã cho trình quét web

def get_selenium[]:                           
options = webdriver.ChromeOptions[]
options.add_argument['--ignore-certificate-errors']
options.add_argument['--incognito']
options.add_argument['headless']
driver = webdriver.Chrome[chrome_options=options]
return [driver]
0

Khi chúng tôi có thể sử dụng thông tin mà ngay cả trình duyệt cũng sử dụng để xử lý phân trang, việc tự sao chép thông tin đó để quét web khá dễ dàng

Bây giờ hãy xem thêm một ví dụ nữa

Xử lý các trang web có phản hồi HTML

Trong phần trước, chúng ta đã xem xét các phản hồi JSON để tìm ra thời điểm ngừng cạo. Ví dụ khá đơn giản vì phản hồi có dấu hiệu rõ ràng về thời điểm đến trang cuối cùng. Thật không may, một số trang web không cung cấp phản hồi và/hoặc chỉ dẫn có cấu trúc khi không còn trang nào để tìm kiếm, vì vậy người ta phải thực hiện nhiều công việc hơn để trích xuất ý nghĩa từ những gì có sẵn. Ví dụ tiếp theo là về một trang web đòi hỏi sự sáng tạo để xử lý đúng cách phân trang của nó

Mở Công cụ dành cho nhà phát triển bằng cách nhấn F12 trong trình duyệt của bạn, chuyển đến tab Mạng rồi chọn XHR. Điều hướng đến https. //techinstr. myshopify. com/bộ sưu tập/tất cả. Bạn sẽ nhận thấy rằng ban đầu có 8 sản phẩm được tải

Nếu chúng tôi cuộn xuống, 8 sản phẩm tiếp theo sẽ được tải. Ngoài ra, hãy chú ý những điều sau đây

  • Tổng số sản phẩm là 132

  • URL của trang chỉ mục khác với các trang còn lại

  • Phản hồi là HTML, không có cách rõ ràng để xác định khi nào nên dừng

Để xử lý phân trang cho trang web này, trước tiên chúng tôi sẽ tải trang chỉ mục và trích xuất số lượng sản phẩm. Chúng tôi đã quan sát thấy rằng 8 sản phẩm được tải trong một yêu cầu. Với dữ liệu này, bây giờ chúng ta có thể tính toán số lượng trang như sau

Bằng cách sử dụng toán học. ceil, chúng ta sẽ nhận được trang cuối cùng, trang này sẽ cho chúng ta 17. Lưu ý rằng nếu bạn sử dụng chức năng làm tròn, trong một số trường hợp, bạn có thể bị thiếu một trang. Ví dụ: nếu có 132 sản phẩm và mỗi yêu cầu tải 5 sản phẩm, điều đó có nghĩa là có 132/5 = 26. 4 trang. Trong thực tế, điều đó có nghĩa là chúng ta phải kiểm tra 27 trang. Sử dụng chức năng trần đảm bảo rằng các trang luôn được làm tròn. Trong ví dụ này, toán học. trần sẽ trả về 27, trong khi vòng sẽ trả về 26

Ngoài việc không cung cấp điều kiện dừng rõ ràng, trang web này còn yêu cầu một người thực hiện các yêu cầu sau yêu cầu đầu tiên trong khi cung cấp dữ liệu phiên liên quan. Nếu không, nó sẽ chuyển hướng trở lại trang đầu tiên. Để tiếp tục sử dụng dữ liệu phiên nhận được từ trang đầu tiên, chúng tôi cũng sẽ cần sử dụng lại phiên thay vì tạo phiên mới cho mỗi trang

Mã hoàn chỉnh cho trình quét web này như sau

def get_selenium[]:                           
options = webdriver.ChromeOptions[]
options.add_argument['--ignore-certificate-errors']
options.add_argument['--incognito']
options.add_argument['headless']
driver = webdriver.Chrome[chrome_options=options]
return [driver]
1

Cách thức hoạt động của Load More rất giống với cách hoạt động của cuộn vô hạn. Sự khác biệt duy nhất là cách tải trang tiếp theo được kích hoạt trên trình duyệt. Bởi vì chúng tôi không sử dụng trình duyệt mà là tập lệnh, sự khác biệt duy nhất sẽ là phân tích phân trang chứ không phải bản thân việc cạo

Mở https. // lịch sử thông minh. org/americas-before-1900/ bằng Công cụ dành cho nhà phát triển [F12] và nhấp vào Tải thêm trong trang

Bạn sẽ thấy rằng phản hồi ở định dạng JSON với một thuộc tính còn lại. Các quan sát chính như sau

  • Mỗi yêu cầu nhận được 12 kết quả

  • Giá trị còn lại giảm đi 12 với mỗi lần nhấp vào Tải thêm

  • Nếu chúng tôi đặt trang giá trị thành 1 trong URL API, nó sẽ nhận được trang đầu tiên của kết quả – https. // lịch sử thông minh. org/wp-json/smthstapi/v1/objects?tag=938&page=1

Trong trường hợp cụ thể này, tác nhân người dùng cũng cần được đặt để tác nhân này hoạt động chính xác. Đoạn mã sau xử lý loại phân trang này trong quét web

def get_selenium[]:                           
options = webdriver.ChromeOptions[]
options.add_argument['--ignore-certificate-errors']
options.add_argument['--incognito']
options.add_argument['headless']
driver = webdriver.Chrome[chrome_options=options]
return [driver]
2

Sự kết luận

Trong bài viết này, chúng tôi đã khám phá các ví dụ khác nhau về phân trang trong quét web. Có thể có nhiều cách trang web sử dụng để hiển thị phân trang. Để hiểu nó hoạt động như thế nào, điều quan trọng là phải xem đánh dấu HTML, cũng như lưu lượng truy cập mạng bằng Công cụ dành cho nhà phát triển. Ngoài ra, hướng dẫn này đã kiểm tra bốn loại phân trang rộng rãi và cách xử lý các loại phân trang này. Ngay cả khi bạn gặp một cái gì đó mới, bạn sẽ có thể tìm ra nó dựa trên bài viết này

Nếu bạn muốn tìm hiểu thêm về quét web hoặc sử dụng proxy, hãy xem blog của chúng tôi và tìm thêm nội dung thú vị. từ các mẹo về cách thu thập dữ liệu trang web mà không bị chặn cho đến cuộc thảo luận chuyên sâu về tính hợp pháp của việc quét web. Ngoài ra, đừng ngần ngại dùng thử miễn phí chức năng của trình quét web đa năng của chúng tôi

Thông tin về các Tác giả

Vejune Tamuliunaite

Cựu giám đốc nội dung sản phẩm

Vejune Tamuliunaite là cựu Giám đốc nội dung sản phẩm tại Oxylabs với niềm đam mê thử nghiệm giới hạn của mình. Sau nhiều năm làm công việc viết kịch bản, cô ấy chuyển sang lĩnh vực công nghệ và bị mê hoặc bởi việc trở thành cốt lõi của việc tạo ra tương lai. Khi không viết bài chuyên sâu, Vejune thích dành thời gian hòa mình vào thiên nhiên và xem những bộ phim khoa học viễn tưởng kinh điển. Ngoài ra, cô ấy có thể thuộc lòng kịch bản Chiến tranh giữa các vì sao.

Tất cả thông tin trên Blog Oxylabs được cung cấp trên cơ sở "nguyên trạng" và chỉ dành cho mục đích thông tin. Chúng tôi không đại diện và từ chối mọi trách nhiệm liên quan đến việc bạn sử dụng bất kỳ thông tin nào có trên Oxylabs Blog hoặc bất kỳ trang web của bên thứ ba nào có thể được liên kết trong đó. Trước khi tham gia vào các hoạt động cạo dưới bất kỳ hình thức nào, bạn nên tham khảo ý kiến ​​​​của cố vấn pháp lý của mình và đọc kỹ các điều khoản dịch vụ của trang web cụ thể hoặc nhận giấy phép cạo

Chủ Đề