前言
公司有个项目大致工作流程为客户批量发送url,我们拿到后对这批url进行数值和评论的采集,网站呢是有个限制范围的(即配置库),普通的网站直接根据配置采集即可,但有些网站则需要生成cookie才能访问到内容,之前是在系统内嵌入了selenium无头浏览器,生成cookie后存入redis缓存下载,后续的采集则不生成cookie以节省时间。总是觉得扩展性不好,后续如有其他项目需要则还要copy一遍,就想着将其写成web服务,预先开启若干个浏览器,请求过来直接开启一个tab即可,速度应该会有所改善。
pyppeteer
pyppeteer运行需要使用chromium浏览器,如果电脑上没有,则会在首次运行时安装,但是需要fq。我使用的是centos,可以通过yum安装
yum -y update
yum install -y epel-release
yum install -y chromium
- 需要指定用户文件目录,否则抛出此异常
- 需要在指定此参数
- 基本参数如下
browser = await launch(headless=True,executablePath="/bin/chromium-browser",args=["--no-sandbox"],userDataDir="/data/spider/chrome/")
- 访问带有跳转行为的链接,有时会抛出此异常
pyppeteer.errors.NetworkError: Protocol error Network.getCookies: Target close
解决方案:
#降低websockets版本
pip uninstall websockets
pip install websockets==6.0
修改User-Agent
await page.setUserAgent(“Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.157 Safari/537.36”)
修改浏览器特征
- 部分网站有webdriver检测,需要在goto语句后,异步执行修改特征的js代码(在之前执行的话无效)
webdriver_js = '''() =>{
Object.defineProperties(navigator,{
webdriver:{
get: () => false
}
})
}
'''
await page.goto(url)
await page.evaluate(webdriver_js)
cookie的获取
预先设置好页面成功打开时的特征,我这里是写死的以某个元素的id为准,浏览器等待指定id的元素出现即代表cookie获取成功,保存时默认为10分钟,亦根据返回的cookie所携带的过期时间进行存储。
Flask
因为只是写一个简单的web服务,基本没什么好说的,部署使用gunicorn,
nohup gunicorn -w 2 -b 127.0.0.1:5000 app:app >/dev/null &
结果
请求结果
redis缓存
结语
代码地址
这只是最简单的方式,很多逻辑没有实现,觉得有用的话可以自己增加一些功能模块。