浏览器抓取网页( 另一个内部系统导出数据存到数据库做分析方案)
优采云 发布时间: 2022-04-15 08:44浏览器抓取网页(
另一个内部系统导出数据存到数据库做分析方案)
Selenium爬虫实践:ajax请求抓包,浏览器退出
2022-04-07 16:00 软件测试 Mumu
前言
最近忙于公司内部制度,累了。我需要从另一个内部系统导出数据并将其存储在数据库中进行分析。有很多数据采集工作,但是我也无法直接获取到那个系统的接口,也很难,只能爬虫,但是cookie还是经常失效。为了不每次登录失败都来找我重新注入cookie,我写了一个手机版的网页后台控制selenium的自动登录,拦截token和cookie。
Ajax请求抓包方案
找资料的过程真的很痛苦,好在这段时间没有浪费,问题终于解决了……
根据查到的资料,在Selenium中抓取ajax请求中的数据有几种方式。
· 使用本地代理:browsermob-proxy
·使用selenium的execute js函数注入ajax hook并执行,然后在本地开一个服务器接收截取的ajax数据
·使用第三方库selenium-wire,这是GitHub上的一个开源项目,可以直接截取response_code和body。原则也应该是代理
·开启selenium的性能捕获,可以在性能日志中做修改拦截response_body
使用本地代理
本文使用代理服务器Browsermob-Proxy,它是用Java编写的,有一个python封装的接口包,方便交互...
先去下载:
安装python包:
pip install browsermob-proxy
代码中用到,这里截取了项目的部分代码,随便看看,完整代码可以看官网文档或者参考资料~
有几个坑需要注意,我在代码中标注了。
# 创建代理服务器
self.server =服务器(
#windows是bat,如果linux是另一种不带后缀的
r'path\bin\browsermob-proxy.bat',
# 这里可以自定义端口
选项={'端口':9090}
)
# 这里启动服务器,有机会再关掉,否则下次使用时端口占用会冲突
self.server.start()
# 注意这里一定要trustAllServers,否则selenium后面会报error_tunnel错误
self.proxy = self.server.create_proxy(params={'trustAllServers': 'true'})
# 为 selenium 设置代理
选项 = ChromeOptions()
options.add_argument('
--忽略证书错误')
options.add_argument(f'--proxy-server={self.proxy.proxy}')
self.driver = webdriver.Chrome(options=options)
使用代理抓包,我的项目需要从ajax请求的头部提取token和cookie。截取关键部分的代码如下:
self.proxy.new_har('自己创建捕获名称', options={'captureHeaders': True, 'captureContent': True})
# 找到需要点击的元素
elem_query =
self.driver.find_element_by_css_selector(elem_css_selector)
elem_query.click()
# 点击按钮后,等待获取数据
时间.sleep(5)
结果 = self.proxy.har
数据 = {}
输入结果['log']['entries']:
url = 条目['请求']['url']
# 根据URL查找数据接口
如果 'xxx/query' 在 url:
_response = 条目['响应']
_content = _response['content']['text']
对于条目中的项目['request']['headers']:
# 提取头部中的token
如果项目['名称'] == '授权':
数据['授权'] = 项目['价值']
# 提取头部中的cookie
如果项目['名称'] == 'Cookie':
数据['cookie'] = 项目['值']
休息
打印(数据)
上面的代码也不是完整的代码,但是抓包的具体过程已经完整表达了。有需要的同学可以根据自己的实际需要进行编码。只要能抓到数据,一切都好说~
浏览器和代理服务器注销
这个没什么好写的,不过也有个小坑,浇水吧~
从上面的代码也可以看出,我写了一个类来操作Selenium。程序执行后,必须关闭代理和服务器。否则selenium会留下一个chromedriver.exe进程在后台长期占用资源。,系统内存已满。
我在类的__del__方法中添加了关闭代理服务器和浏览器的代码,如下:
def __del__(self):
print('SeleniumFxxkUnicom 已被删除。')
self.proxy.close()
self.server.stop()
为了赢得
self.driver.window_handles:
self.driver.switch_to.window(win)
self.driver.close()
os.system('taskkill /im chromedriver.exe /F')
注意这个循环的 driver.close() 。__del__ 中无法正常执行 driver.quit()。按理说quit是最好的退出方式,但是他还需要导入一些乱七八糟的模块,导致我在这个__del__执行失败,只好曲线曲线救国,先关闭所有标签,然后使用系统命令结束进程...