Python网络爬取 动态网站
在本章中,让我们学习如何在动态网站上进行网络爬虫,以及所涉及的详细概念。
简介
网络爬取是一项复杂的任务,如果网站是动态的,其复杂性会成倍增加。根据联合国全球网络可访问性审计报告,超过70%的网站是动态的,它们的功能依赖于JavaScript。
动态网站实例
让我们看一个动态网站的例子,了解为什么它很难被搜刮。在这里,我们将以一个名为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)
输出
[ ]
上面的输出显示,这个例子的搜刮器未能爬取信息,因为我们试图找到的
<
div>元素是空的。
从动态网站搜刮数据的方法
我们已经看到,搜刮器无法从动态网站上搜刮到信息,因为数据是用JavaScript动态加载的。在这种情况下,我们可以使用以下两种技术,从依赖JavaScript的动态网站中爬取数据 −
- 逆向工程JavaScript
- 渲染JavaScript
逆向工程JavaScript
被称为逆向工程的过程将是有用的,让我们了解数据是如何被网页动态加载的。
为了做到这一点,我们需要点击指定URL的 检查元素 标签。接下来,我们将点击 NETWORK 标签,找到所有对该网页的请求,包括路径为 /ajax 的search.json 。 我们可以用下面的Python脚本来代替从浏览器或通过NETWORK标签访问AJAX数据:
import requests
url=requests.get('http://example.webscraping.com/ajax/search.json?page=0&page_size=10&search_term=a')
url.json()
例子
上面的脚本允许我们通过使用Python的json方法来访问JSON响应。同样,我们可以下载原始的字符串响应,通过使用Python的json.load方法,我们也可以加载它。我们是在以下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)))
运行上述脚本后,我们将得到以下输出,这些记录将被保存在名为country.txt的文件中。
输出
Searching with a
adding 15 records from the page 0
adding 15 records from the page 1
...
渲染JavaScript
在上一节中,我们对网页进行了逆向工程,了解了API是如何工作的,以及我们如何使用它来检索单个请求的结果。然而,在进行逆向工程时,我们可能会面临以下困难
- 有时网站可能非常困难。例如,如果网站是用先进的浏览器工具,如Google Web Toolkit(GWT)制作的,那么产生的JS代码将是机器生成的,很难理解和进行反向工程。
-
一些更高级的框架,如 React.js ,通过抽象已经很复杂的JavaScript逻辑,会使逆向工程变得困难。
解决上述困难的方法是使用浏览器渲染引擎,解析HTML,应用CSS格式化,并执行JavaScript来显示网页。
例子
在这个例子中,为了渲染Java Script,我们将使用一个熟悉的Python模块Selenium。下面的Python代码将在Selenium的帮助下渲染一个网页-
首先,我们需要从Selenium导入webdriver,如下所示
from selenium import webdriver
现在,根据我们的要求,提供我们已经下载的网络驱动器的路径
path = r'C:\\Users\\gaurav\\Desktop\\Chromedriver'
driver = webdriver.Chrome(executable_path = path)
现在,提供我们想在网络浏览器中打开的网址,现在由我们的Python脚本控制。
driver.get(['http://example.webscraping.com/search'](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()