Scraping Python Web - Trang web động
Trong chương này, chúng ta hãy tìm hiểu cách thực hiện thao tác quét web trên các trang web động và các khái niệm liên quan một cách chi tiết.
Giới thiệu
Gỡ bỏ trang web là một công việc phức tạp và sự phức tạp sẽ tăng lên gấp bội nếu trang web là động. Theo Kiểm toán Toàn cầu về Khả năng Tiếp cận Web của Liên hợp quốc, hơn 70% các trang web có bản chất động và chúng dựa vào JavaScript cho các chức năng của chúng.
Ví dụ về trang web động
Hãy để chúng tôi xem xét một ví dụ về một trang web động và biết về lý do tại sao nó rất khó để loại bỏ. Ở đây chúng ta sẽ lấy ví dụ về việc tìm kiếm từ một trang web có tênhttp://example.webscraping.com/places/default/search.Nhưng làm thế nào chúng ta có thể nói rằng trang web này có tính chất động? Nó có thể được đánh giá từ đầu ra của tập lệnh Python sau sẽ cố gắng lấy dữ liệu từ trang web được đề cập ở trên -
import re
import urllib.request
response = urllib.request.urlopen('http://example.webscraping.com/places/default/search')
html = response.read()
text = html.decode()
re.findall('(.*?)',text)
Đầu ra
[ ]
Kết quả ở trên cho thấy rằng trình quét ví dụ không thể trích xuất thông tin vì phần tử <div> mà chúng tôi đang cố gắng tìm trống.
Các phương pháp tiếp cận để thu thập dữ liệu từ các trang web động
Chúng tôi đã thấy rằng trình quét không thể thu thập thông tin từ một trang web động vì dữ liệu được tải động bằng JavaScript. Trong những trường hợp như vậy, chúng tôi có thể sử dụng hai kỹ thuật sau để thu thập dữ liệu từ các trang web phụ thuộc JavaScript động:
- JavaScript Kỹ thuật Đảo ngược
- Hiển thị JavaScript
JavaScript Kỹ thuật Đảo ngược
Quá trình được gọi là kỹ thuật đảo ngược sẽ hữu ích và cho phép chúng tôi hiểu cách dữ liệu được tải động bởi các trang web.
Để thực hiện việc này, chúng ta cần nhấp vào inspect elementcho một URL được chỉ định. Tiếp theo, chúng tôi sẽ nhấp vàoNETWORK để tìm tất cả các yêu cầu được thực hiện cho trang web đó bao gồm cả search.json với đường dẫn là /ajax. Thay vì truy cập dữ liệu AJAX từ trình duyệt hoặc qua tab NETWORK, chúng ta cũng có thể thực hiện việc đó với sự trợ giúp của tập lệnh Python sau:
import requests
url=requests.get('http://example.webscraping.com/ajax/search.json?page=0&page_size=10&search_term=a')
url.json()
Thí dụ
Tập lệnh trên cho phép chúng tôi truy cập phản hồi JSON bằng cách sử dụng phương thức Python json. Tương tự, chúng ta có thể tải xuống phản hồi chuỗi thô và bằng cách sử dụng phương thức json.loads của python, chúng ta cũng có thể tải nó. Chúng tôi đang làm điều này với sự trợ giúp của tập lệnh Python sau. Về cơ bản, nó sẽ loại bỏ tất cả các quốc gia bằng cách tìm kiếm chữ cái trong bảng chữ cái 'a' và sau đó lặp lại các trang kết quả của các câu trả lời JSON.
import requests
import string
PAGE_SIZE = 15
url = 'http://example.webscraping.com/ajax/' + 'search.json?page={}&page_size={}&search_term=a'
countries = set()
for letter in string.ascii_lowercase:
print('Searching with %s' % letter)
page = 0
while True:
response = requests.get(url.format(page, PAGE_SIZE, letter))
data = response.json()
print('adding %d records from the page %d' %(len(data.get('records')),page))
for record in data.get('records'):countries.add(record['country'])
page += 1
if page >= data['num_pages']:
break
with open('countries.txt', 'w') as countries_file:
countries_file.write('n'.join(sorted(countries)))
Sau khi chạy tập lệnh trên, chúng ta sẽ nhận được kết quả sau và các bản ghi sẽ được lưu trong tệp có tên là country.txt.
Đầu ra
Searching with a
adding 15 records from the page 0
adding 15 records from the page 1
...
Hiển thị JavaScript
Trong phần trước, chúng tôi đã thiết kế ngược trên trang web về cách hoạt động của API và cách chúng tôi có thể sử dụng nó để truy xuất kết quả trong một yêu cầu duy nhất. Tuy nhiên, chúng tôi có thể gặp phải những khó khăn sau khi thực hiện thiết kế ngược -
Đôi khi các trang web có thể rất khó. Ví dụ: nếu trang web được tạo bằng công cụ trình duyệt nâng cao như Bộ công cụ Web của Google (GWT), thì mã JS tạo ra sẽ được tạo bằng máy và khó hiểu và khó hiểu cũng như được thiết kế ngược.
Một số khuôn khổ cấp cao hơn như React.js có thể gây khó khăn cho kỹ thuật đảo ngược bằng cách trừu tượng hóa logic JavaScript vốn đã phức tạp.
Giải pháp cho những khó khăn trên là sử dụng công cụ kết xuất trình duyệt phân tích cú pháp HTML, áp dụng định dạng CSS và thực thi JavaScript để hiển thị một trang web.
Thí dụ
Trong ví dụ này, để hiển thị Java Script, chúng ta sẽ sử dụng một mô-đun Python quen thuộc Selenium. Đoạn mã Python sau sẽ hiển thị một trang web với sự trợ giúp của Selenium:
Đầu tiên, chúng ta cần nhập webdriver từ selen như sau:
from selenium import webdriver
Bây giờ, cung cấp đường dẫn của trình điều khiển web mà chúng tôi đã tải xuống theo yêu cầu của chúng tôi -
path = r'C:\\Users\\gaurav\\Desktop\\Chromedriver'
driver = webdriver.Chrome(executable_path = path)
Bây giờ, cung cấp url mà chúng tôi muốn mở trong trình duyệt web đó hiện được điều khiển bởi tập lệnh Python của chúng tôi.
driver.get('http://example.webscraping.com/search')
Bây giờ, chúng ta có thể sử dụng ID của hộp công cụ tìm kiếm để thiết lập phần tử cần chọn.
driver.find_element_by_id('search_term').send_keys('.')
Tiếp theo, chúng ta có thể sử dụng java script để thiết lập nội dung hộp chọn như sau:
js = "document.getElementById('page_size').options[1].text = '100';"
driver.execute_script(js)
Dòng mã sau cho thấy rằng tìm kiếm đã sẵn sàng để được nhấp vào trang web -
driver.find_element_by_id('search').click()
Dòng mã tiếp theo cho thấy rằng nó sẽ đợi 45 giây để hoàn thành yêu cầu AJAX.
driver.implicitly_wait(45)
Bây giờ, để chọn các liên kết quốc gia, chúng ta có thể sử dụng bộ chọn CSS như sau:
links = driver.find_elements_by_css_selector('#results a')
Giờ đây, văn bản của mỗi liên kết có thể được trích xuất để tạo danh sách các quốc gia -
countries = [link.text for link in links]
print(countries)
driver.close()