在进行爬虫的时候,有时候我们在网页中看到的数据是一个样子的,但是抓取到的数据却是另外一个样子的。这是为什么呢?这个时候啊很可能我们抓取的是动态网页。动态网页的代码虽然没有改变,但是显示的内容却是可以随着时间、环境或者数据库操作的结果二发生改变的。动态网页一般使用被称为 AJAX 的快速动态创建网页技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实现异步更新。那么这种网页该如何进行抓取呢?我们可以考虑使用如下两种方法。
1. 分析页面请求,查找真实请求的URL
既然 AJAX 技术是在后台与服务器交换数据,只要有数据发送过来,就肯定有发送到服务器的请求,只需找出它加载出页面的真实请求,然后构造并发送请求即可。
2. 使用Selenium模拟浏览器行为
Selenium是一个自动化测试工具,被广泛的用来做爬虫,在爬虫中主要使用Selenium解决动态网页的加载和渲染功能。Selenium 可以用代码模拟操作浏览器,模拟人的操作。可以使用 Selenium,配合 headless 的浏览器(如:phantomjs、headless Chrome)来加载和渲染网页,然后提取需要的信息。
案例
1. 链家经纪人页面分析
我们来对移动端的 链家经纪人页面 进行分析,相比于 PC 端,移动端的网页更为简单、简洁。所以如果一个网页有移动端的话,我们优先选择移动端网页进行爬取。打开网页拉动滚动条,将其拉到底,添加一些数据进来,我们发现 NetWork 里出现了很多的请求信息,这些请求大部分都是以 jpg 结束的图片请求,但是我们仔细观察,就能发现一项比较特殊的请求,如下:
我们继续滑动滚动条,又会发现类似的请求,我们将该请求链接复制出来,单独打开,发现它是不同经纪人的请求页面。我们对该链接进行分析,发现后面有一项 offset 的值一直在改变,而且每次以 15 增加,会请求到新的 15 条数据。因此你,我们只需要更改 offset 的值即可请求不同的页面。至此,我们已经发现了该网站 URL 的构造规律了,下面就可以编写代码进行爬取了。
# -*- coding: utf-8 -*-
# # @Author: lemon
# # @Date: 2019-09-19 18:18
# # @Last Modified by: lemon
# # @Last Modified time: 2019-09-19 18:42
# # @function: 爬取链家经纪人数据
import requests
import time
from lxml import etree
import pandas as pd
# 存储 DataFrame 中用到的数据
data = {
'姓名': [],
'职位': [],
'评分': []
}
def spider(list_url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
response = requests.get(list_url, headers=headers)
time.sleep(5)
sel = etree.HTML(response.text)
# 先爬取每一位经纪人的整体代码段
agent_list = sel.xpath('//li[@class="pictext flexbox box_center_v lazyload_ulog"]')
for agent in agent_list:
agent_name = agent.xpath('div/div[2]/div[1]/span[1]/a/text()')[0].strip() # 姓名
agent_level = agent.xpath('div/div[2]/div[1]/span[2]/text()')[0].strip() # 职位
agent_score = agent.xpath('div/div[2]/div[1]/span[3]/span[1]/text()')[0].strip() # 评分
print(agent_name, agent_level, agent_score)
data['姓名'].append(agent_name)
data['职位'].append(agent_level)
data['评分'].append(agent_score)
def write_data(data):
frame = pd.DataFrame(data)
frame.to_excel('链家经纪人数据.xlsx')
if __name__ == '__main__':
for i in range(10):
# 根据加载的时候 offset 的变化规律, 构造不同页面的 URL
url = 'https://m.lianjia.com/cs/jingjiren/?page_size=15&_t=1&offset=' + str(i * 15)
print(f'正在爬取 page {i + 1}...')
spider(url)
write_data(data)
这是我们最终爬取到的经纪人数据:
2. Selenium 请求百度
由于 Selenium 不是 Python 的标准库,因此我们首先需要安装 Selenium 库。
pip install selenium
Selenium 需要使用 chromedriver 来驱动 Chrome 浏览器,我们需要下载与操作系统对应的版本,可参考 ChromeDriver与Chrome版本对应参照表及ChromeDriver下载链接 进行下载安装。
Selenium 在使用 chromedriver 时,既可以把 chromedriver添加到系统的环境变量中,也可以直接在代码中指明 chromedriver 所在的目录。
下面我们使用 Selenium 访问百度首页
# -*- coding: utf-8 -*-
# # @Author: lemon
# # @Date: 2019-09-19 19:00
# # @Last Modified by: lemon
# # @Last Modified time: 2019-09-19 19:10
# # @function: Selenium 打开百度
# %%1 从 selenium 中引入 webdriver
from selenium import webdriver
driver = webdriver.Chrome('E:\ChromeDriver\chromedriver.exe') # 初始化 webdriver
driver.get('https://www.baidu.com/') # 使用 webdriver 打开百度首页
search_box = driver.find_element_by_xpath('//*[@id="kw"]') # 使用 xpath 找到搜索框
search_box.send_keys('python') # 在搜索框中搜索关键字
submit = driver.find_element_by_xpath('//*[@id="su"]') # 使用 xpath 找到搜索按钮
submit.click() # 点击搜索按钮进行搜索
可观察到如下效果:我们的 Chrome 浏览器正在收到自动测试软件的控制
后续的文章我们为大家示例:如何使用 Selenium 爬取新浪微博的网站,进一步加强大家对于 Selenium 的使用。