📜  Python Web爬网-动态网站

📅  最后修改于: 2020-11-07 08:04:39             🧑  作者: Mango


在本章中,让我们学习如何在动态网站上执行Web抓取以及详细涉及的概念。

介绍

Web抓取是一项复杂的任务,如果网站是动态的,则复杂性会成倍增加。根据联合国网络无障碍全球审计,超过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)

输出

[ ]

上面的输出显示示例刮板示例未能提取信息,因为我们尝试查找的

元素为空。

从动态网站收集数据的方法

我们已经看到,由于数据是使用JavaScript动态加载的,因此抓取器无法从动态网站中抓取信息。在这种情况下,我们可以使用以下两种技术从依赖于动态JavaScript的网站抓取数据-

  • 逆向工程JavaScript
  • 渲染JavaScript

逆向工程JavaScript

称为逆向工程的过程将非常有用,它可以使我们了解网页如何动态加载数据。

为此,我们需要单击指定元素检查元素选项卡。接下来,我们将单击NETWORK选项卡以查找针对该网页的所有请求,包括带有/ ajax路径的search.json。不用从浏览器或通过NETWORK选项卡访问AJAX数据,我们也可以在以下Python脚本的帮助下进行操作-

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.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))) 

运行上面的脚本后,我们将获得以下输出,并且记录将保存在名为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脚本,我们将使用熟悉的Python模块Selenium。以下Python代码将在Selenium的帮助下呈现网页-

首先,我们需要从硒中导入webdriver,如下所示:

from selenium import webdriver

现在,提供我们根据要求下载的Web驱动程序的路径-

path = r'C:\\Users\\gaurav\\Desktop\\Chromedriver'
driver = webdriver.Chrome(executable_path = path)

现在,提供我们要在该网络浏览器中打开的URL,该URL现在由我们的Python脚本控制。

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()