Python Web Scraping 简明教程
Python Web Scraping - Dynamic Websites
在本章中,让我们学习如何在动态网站上执行网络抓取,以及其中涉及的概念的详细信息。
Dynamic Website Example
让我们看一个动态网站的示例,并了解为什么很难抓取。在这里,我们将以从名为 http://example.webscraping.com/places/default/search. 的网站中搜索为例。但是我们如何判断该网站的性质是动态的?可以从以下 Python 脚本的输出中进行判断,该脚本将尝试从上述网页中抓取数据 −
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)
Approaches for Scraping data from Dynamic Websites
我们已经看到,由于数据通过 JavaScript 动态加载,因此,抓取器无法抓取动态网站中的信息。在这样的情况下,我们可以使用以下两种技术从依赖 JavaScript 的动态网站中抓取数据−
-
Reverse Engineering JavaScript
-
Rendering JavaScript
Reverse Engineering JavaScript
名为逆向工程的过程很有用,可以让我们了解网页如何动态加载数据。
为此,我们需要为特定 URL 点击 inspect element 标签。接下来,我们将单击 NETWORK 标签来查找为该网页发出的所有请求,包括具有 /ajax 路径的 search.json。我们可以借助以下 Python 脚本访问 AJAX 数据(而不是通过浏览器或通过 NETWORK 访问),也可以使用此脚本:
import requests
url=requests.get('http://example.webscraping.com/ajax/search.json?page=0&page_size=10&search_term=a')
url.json()
Example
上面的脚本允许我们使用 Python json 方法访问 JSON 响应。同样,我们可以下载原始字符串响应,并使用 Python 中的 json.loads 方法加载响应。我们可以借助以下 Python 脚本执行此操作。它将通过搜索字母“a”,然后迭代 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)))
在运行上面的脚本后,我们将获得以下输出,并且记录将保存到名为 countries.txt 的文件中。
Rendering JavaScript
在上一个部分中,我们对网页执行了逆向工程,了解了 API 的工作原理,以及我们如何使用它来在一单个请求中检索结果。但是,在进行逆向工程时,我们可能会遇到以下困难−
-
有时,网站可能会非常困难。例如,如果该网站是使用高级浏览器工具(例如 Google Web Toolkit (GWT))制作的,那么生成的 JS 代码将是机器生成的,并且难以理解和逆向工程。
-
像 React.js 这样的某些高层次框架可以通过抽象已经很复杂的 JavaScript 逻辑来增加逆向工程的难度。
解决上述困难的方法是使用浏览器渲染引擎,该引擎可以解析 HTML、应用 CSS 格式并执行 JavaScript 以显示网页。
Example
在此示例中,我们将使用一个知名的 Python 模块 Selenium 来渲染 Java Script。以下 Python 代码将借助 Selenium 渲染一个网页−
首先,我们需要从 selenium 中导入 webdriver,如下所示 −
from selenium import webdriver
现在,提供我们根据要求下载的 web driver 的路径 −
path = r'C:\\Users\\gaurav\\Desktop\\Chromedriver'
driver = webdriver.Chrome(executable_path = path)
现在,提供我们想要在现在由我们的 Python 脚本控制的 web 浏览器中打开的 url。
driver.get('http://example.webscraping.com/search')
现在,我们可以使用搜索工具箱的 ID 为要选择的元素进行设置。
driver.find_element_by_id('search_term').send_keys('.')
接下来,我们可以使用 Java 脚本将选择框内容设置为如下 −
js = "document.getElementById('page_size').options[1].text = '100';"
driver.execute_script(js)
下面一行代码显示,搜索已准备好点击网页 −
driver.find_element_by_id('search').click()
下一行代码显示,它将等待 45 秒以完成 AJAX 请求。
driver.implicitly_wait(45)
现在,为了选择国家链接,我们可以使用 CSS 选择器,如下所示 −
links = driver.find_elements_by_css_selector('#results a')
现在可以提取每个链接的文本以创建国家列表 −
countries = [link.text for link in links]
print(countries)
driver.close()