动态渲染反爬虫
动态网页比静态网页更具有交互性,能给用户提供更好的体验
动态网页中常见的表现形式有 下拉刷新,点击切换和悬停显示等
由 JavaScript 改变 HTML DOM 导致页面内容发生变化的现象称为动态渲染
动态渲染的通用解决办法
如果每次遇到很麻烦的动态渲染页面,都需要猜接口参数,跟进和分析 JavaScript 代码逻辑
那么耗费的时间成本就很高了
当目标网站发生产品迭代升级或针对爬虫有意改动代码,爬虫工程师就需要做对应的调整
可能目标网站的前端工程师只花费了 2 小时编写用于加密请求参数的代码,而爬虫工程师却需要花费 3 天甚至更多时间才能分析出正确的计算逻辑
那么我们就可以用渲染工具,来模拟用户的一些操作,比如点击,滑动和拖拽
其中常用的是 Puppeteer,Splash,和 Selenium这三种工具
Selenium套件
from selenium import webdriver url = 'http://www.porters.vip/verify/sign' # 初始化浏览器对象 brower = webdriver.Chrome() # 向指定网址发起 GET 请求 brower.get(url) # 使用 CSS 选择器定位按钮,并点击按钮 brower.find_element_by_css_selector('#fetch_button').click() # 使用 CSS 选择器定位文本,并取出文本内容 resp = brower.find_element_by_css_selector('#content').text # 将按钮点击后的网页文本赋值给变量 resp # resp = brower.page_source print(resp) # 程序退出,并关闭浏览器 brower.quit()
异步渲染库 Puppeteer
在 Selenium 套件的支持下,我们很轻松的完成了爬取任务
单 Selenium 套件也有一定的缺陷,当我们使用 Python 中的异步库编写爬虫时,Selenium 就不是那么合适了
异步是目前提升爬虫效率的常用手段之一,越来越多的人讲同步的爬虫代码改写为异步。由于浏览器是以进程方式启动的,所以它无法满足异步爬虫的渲染需求,为什么这么说呢?
异步爬虫可以做到每秒向 300 个页面发起请求,单是要在计算机中开启 300 个浏览器进程或者 300 个标签是很困难的,这会导致阻塞,影响异步爬虫程序的整体效率
如果添加一些加载资源较多的网站或者响应速度很慢的网站,会发现卡顿阻塞所有的请求,这就是同步的缺点,如果用的是多个浏览器对象,即每次请求都初始化一个浏览器对象,虽然可以解决这个问题,但过多的浏览器进程对于系统资源的消耗是非常大的,显然这是一种得不偿失的做法
这时候我们需要一个能够做到与 Selenium 套件相同的总做并且支持异步的渲染工具
Puppetetr 正好可以满足我们的需求,Puppeteer 是 Google 开源的 Node 库,它提供了有个高级 API 开控制 Chrome 浏览器,浏览器中大多数手动执行的操作都可以使用 Puppeteer 完成,更重要的是 Puppeteer 支持异步
Puppeteer 是一个 Node 库,如果你的爬虫程序使用 Node.js 编写的,那么可以直接使用这个库,如果爬虫程序是用 Python 写的,那么久需要用支持 Python 的库 Pypeteer
示例:
import asyncio from pyppeteer import launch async def main(): # 初始化浏览器对象 browser = await launch() # 在浏览器上下文中创建新页面 page = await browser.newPage() # 打开目标网址 await page.goto('http://www.porters.vip/verify/sign') # 点击指定按钮 await page.click('#fetch_button') # 读取页面指定位置的文本 resp = await page.xpath('//*[@id="content"]') text = await (await resp[0].getProperty('textContent')).jsonValue() print(text) # 关闭浏览器对象 await browser.close() asyncio.get_event_loop().run_until_complete(main())