运用抓包爬取动态加载网站--案例一

网站分析

目标网站:https://ghfc.pasteur.fr/eq/

网站截图
我们想收集的是染色体上每个位点的结构化信息,如下图,需点击圆点后才会显示:
目标字段
灰色矩形部分的字段即是目标。

寻找最优爬虫策略

测试及错误分析

因为需要点击圆点后才位点信息才能看到,所以考虑采用因为需要点击圆点后才位点信息才能看到,所以考虑采用 Selenium 进行测试,看是否能通过这个方法获取所有位点的信息。
通常在写爬虫程序前需要对网站进行分析,并做一些简单的测试,确保完整的爬虫脚本能按预期方式执行,至少要尽可能降低出错率。

1
2
3
4
5
6
7
8
9
10
# 导入相关包
from selenium import webdriver
# 使用本地的 chromedriver 创建一个驱动实例
driver = webdriver.Chrome('D:/programs/chromedriver.exe')
# 模拟浏览器打开目标链接
driver.get('https://ghfc.pasteur.fr/eq/')
# 根据id获得第一个染色体上的所有圆点
circles = driver.find_element_by_id('chr1').find_elements_by_tag_name('circle')
# 尝试点击
circles[0].click()

我是在 jupyter notebook 中逐行执行以上代码的,这样可以检查每一步的执行效果。

到最后一行会发现代码抛出一个WebDriverException异常,而我们在弹出的测试浏览器中也没有看到某个位点被点击后显示的信息,说明这个点击操作失败了。先检查一下出错原因:

1
WebDriverException: Message: unknown error: Element <circle cx="286.75098692718603" cy="33.573750000000004" r="3" fill="#0000ff" fill-opacity="0.5" id="rs9976" class="rs"></circle> is not clickable at point (548, 374). Other element would receive the click: <circle cx="286.3416462133789" cy="30.29845" r="3" fill="#4400ba" fill-opacity="0.5" id="rs2451" class="rs"></circle>

“is not clickable” 说明这个位置点击不了,为什么点击不了呢?再看后面,”Other element would receive the click”,并给出另外一个 circle 元素的信息,这说明收到这个点击命令的元素不是我们想要的元素。再看一下原网页:
错误定位
很多圆形位点是相互重叠的,这就解释了为什么有的元素点击不了,因为有其他元素覆盖在它上方。

策略分析

接下来怎么做呢?

我们先看看要面对的数据规模,先统计一下第一个染色体上有多少个位点好了。

1
2
3
len(circles)

# 输出: 1137

第一条染色体就有1137个位点,十条染色体就要上万了,使用 Selenium 这样的自动化测试工具来爬的效率是比较低的。先来测试在这一千多个位点中,可通过 Selenium 进行模拟点击的有多少个。

1
2
3
4
5
6
7
8
9
err_counts = 0
for i in circles:
try:
i.click()
except:
err_counts += 1

print(err_counts)
# 输出:1090

总数为1137,不可点击的元素有1090,这就有点过分了。

如果继续用 Selenium,可以写一个循环,每次遍历所有元素,对可点击的元素进行处理,处理完即通过 Selenium 控制js脚本删除该元素。这样每次循环就删除了位于最上方的元素,使其他的元素有可点击的可能。多轮循环之后理论上可遍历完所有位点。

我没有这么做,因为根据个人之前的爬虫经验,当动态加载的数据量比较大的时候,是有可能通过抓包定位到数据的源地址的。

果不其然,打开 Chrome 控制台,点击 Network 选项,刷新一次网页。
network抓包截图
如上图,可看到在网页基本元素加载完后,出现了一个数据块,里面装着一个 txt 压缩包,点击该压缩包。
txt压缩包截图
可看到该压缩包的URL为https://ghfc.pasteur.fr/data/empathy-10k.txt.gz,将该地址粘贴到 Chrome 地址栏并回车,就下载了该文件。打开文件,发现 txt 中的每一行,便是一个染色体位点的详情信息。
txt内容
至此我们就走了一条捷径,从网站分析直接抵达终点了。

最后可以将 txt 作为结果保存,或者对每一行进行处理,存入数据库,根据具体使用需求而定。

总结

  • 如果网站数据可以通过抓包获得,便可以极大提高爬虫效率,这次抓到的是 txt 文件,有时候得到的是 json,即属于网站的 api 接口。
  • 何时用抓包?当动态加载的数据量比较大时可以考虑,也许有时候会涉及 api 鉴权,那就要另当别论了。