利用selenium抓取网页的ajax请求
部门需要一个自动化脚本,完成web端界面功能的冒烟,并且需要抓取加载页面时的ajax请求,从接口层面判断请求是否成功。查阅了很多资料都没有人有过相关问题的处理经验,在处理过程中也踩了很多坑,所以如果你也有这个需要,就继续往下看吧~
环境及语言:
Python
selenium3.14
为什么selenium不能直接拦截请求body呢?这是Chrome官方故意而为之的,详情可参考这个网址:
https://bugs.chromium.org/p/chromedriver/issues/detail?id=2267&q=performance%20response%20body&can=1
上网引擎搜索后,找到的解决方案有以下三种:
1、走代理,在代理层面截取日志请求;这个如果代理过期,请求就会变得巨慢,所以没有采用,有需要可以自行研究。
2、用selenium-wire,这个是一个GitHub上的开源项目,可以直接截取response_code和body,原理大概翻了一下源码,应该走的也是代理,只不过这个项目替你封装好了。
当时看到的时候真是激动坏了,pip install一下, 问题全部解决。但是当我兴致满满的运行代码时,发现网页报错: err_proxy_connection_failed.心凉了一大半,去开源项目下寻求答案,这个原来不止我这边发生过,可以说是这个开源项目的一个bug,至今为止未被close。不死心的调试了很久,都没能走通这条路,所以含泪放弃。事实说明,还是不要随便相信star只有一两百颗星的项目。开源代码放在下面,万一你那里能走通呢:
https://github.com/wkeeling/selenium-wire
3、开启selenium的性能抓取,在性能日志里面可以做改动,以拦截response_body:
整体的一个思路先概括一下:
结合selenium与Chrome devtool:selenium可开启性能日志,根据性能日志中的Network.responseReceived事件抓取requestId和对应的url ,然后结合selenium提供的execute方法,传入requestId参数,即可获得对应的body回参。
execute_cdp_cmd()方法的源码里面有示例,写的很清楚,可以去看一下,本文也会给出代码示例:
- 3.1 selenium截取开启日志的代码如下:
1 caps = DesiredCapabilities.CHROME
2 caps['goog:loggingPrefs'] = {'performance': 'ALL'}
3
4 def driver():
5 global driver
6 driver = webdriver.Chrome(desired_capabilities=caps)
7 driver.maximize_window()
请注意第二行代码,这是我踩得第一个坑:
很多教程里面给的代码如下:
caps['loggingPrefs'] = {'performance': 'ALL'},用这段代码去打开性能日志,但是这样运行起来是会报错的,原因是自chromedriver, 75.0.3770.8起,就必须这样去运行了。
注意,只打开性能日志还是不能抓取body的,如果你的需求只是判断状态码,那么上面的解决方式已经足够了。
- 3.2 下面记录怎么让我们抓取到返回的消息体:
1、为什么需要获取requestid:
Chrome性能日志的获取需要配合Chrome DevTool的方法一起使用,这个文档详细列出了Chrome提供的domains,定位到domains——network下,可以选取需要的methods:https://chromedevtools.github.io/devtools-protocol/tot/Network/
在这个里面,我选到了自己需要的方法,如下图,可以看到,这里需要传入一个参数,叫做requestId,它是唯一的请求ID,获得这个我们就能抓取到想要的body了。但是这个requestId真是听都没听过,要去从哪里获取呢?这时候就需要去分析一下我们抓取的性能日志里面的事件了。

2、 关于Chrome返回的日志事件,可以参加这个博客,里面有很详细介绍,我就是基于这个博客(https://blog.csdn.net/zhuyiquan/article/details/80148767#networkrequestwillbesent。),分析出自己要用到的事件的——Network.responseReceived,里面含有requestid的返回值。
1 def parse_response_body(driver):
2 """获取requestid"""
3 browser_log = driver.get_log('performance')
4 events = [_process_browser_log_entry(entry) for entry in browser_log]
5 events_response = [event for event in events if 'Network.responseReceived' == event['method']] # 根据Network.responseReceived这个network,解析出requestId
6 for res in events_response:
7 requestId = res["params"]["requestId"]
3、综上,再结合selenium中的方法即可:
1 def execute_cdp_cmd(driver, cmd, cmd_args):
2 return driver.execute("executeCdpCommand", {'cmd': cmd, 'params': cmd_args})['value']
3
4
5 response_body = driver.execute_cdp_cmd('Network.getResponseBody', {'requestId': requestId}
接下来的事情就非常简单了,抓取body,然后利用json进行解析即可。就在我信心满满的时候,现实又给了沉重的一击,在抓取请求的body过程中,程序报错
No resource with given identifier found
这是踩得最大的坑,整整困扰了我五六个小时,以为是自己代码哪里处理的有问题,一直在调试,在网上搜索问题,最后在一个不太相关的关于js的博客里面,看到这么一句话:getResponseBody will error occur when the query returns nothing...
回头去界面手动获取了一下当前运行页面的ajax请求,果然都是没有返回体的请求ORZ。
果断上了try..except..,然后程序就华丽丽的运行起来了!此刻的心情真是又激动又想哭。
后记:
这种需求感觉还是很常见的,毕竟界面元素能否加载成功,看接口返回是最直接最可靠的方法,但是不知道为什么国内好像没有相关的博客(也可能是我手残没有搜到),所以谨以此文做记录,希望有需要的小伙伴不要走我这么多弯路,能够轻轻松松解决问题~~
PS:当时在翻墙的过程中,也搜到了一种解决方法是升级selenium至4,因为selenium 4开始支持与Chrome DevTools 一起获取。但是搜到的只有Java示例,因为对于Java不是很熟悉,所以弃用,在这里一并提供给大家,有需要的可以自取:
https://medium.com/@ohanaadi/chrome-devtools-and-selenium-4-eadab5d755b7
-----------------------我是分割线2021/02/01---------------------------
今天翻阅技术博客的时候,发现了一个开源项目,是通过代理的手段截取的ajax请求,先记录一下资料:
https://github.com/lightbody/browsermob-proxy
利用selenium抓取网页的ajax请求的更多相关文章
- Python爬虫实战八之利用Selenium抓取淘宝匿名旺旺
更新 其实本文的初衷是为了获取淘宝的非匿名旺旺,在淘宝详情页的最下方有相关评论,含有非匿名旺旺号,快一年了淘宝都没有修复这个. 可就在今天,淘宝把所有的账号设置成了匿名显示,SO,获取非匿名旺旺号已经 ...
- 利用Crowbar抓取网页异步加载的内容 [Python俱乐部]
利用Crowbar抓取网页异步加载的内容 [Python俱乐部] 利用Crowbar抓取网页异步加载的内容 在做 Web 信息提取.数据挖掘的过程中,一个关键步骤就是网页源代码的获取.但是出于各种原因 ...
- 利用page_source抓取网页中的URL,进行链接测试
selenium的page_source方法可以获取到页面源码,下面就把它应用到链接测试中. # coding:utf-8 __author__ = 'helen' import re,request ...
- 我的第一个爬虫程序:利用Python抓取网页上的信息
题外话 我第一次听说Python是在大二的时候,那个时候C语言都没有学好,于是就没有心思学其他的编程语言.现在,我的毕业设计要用到爬虫技术,在网上搜索了一下,Python语言在爬虫技术这方面获得一致好 ...
- 利用jsoup抓取网页图片
jsoup简介 jsoup is a Java library for working with real-world HTML. It provides a very convenient API ...
- 利用Selenium爬取淘宝商品信息
一. Selenium和PhantomJS介绍 Selenium是一个用于Web应用程序测试的工具,Selenium直接运行在浏览器中,就像真正的用户在操作一样.由于这个性质,Selenium也是一 ...
- selenium抓取动态网页数据
1.selenium抓取动态网页数据基础介绍 1.1 什么是AJAX AJAX(Asynchronouse JavaScript And XML:异步JavaScript和XML)通过在后台与服务器进 ...
- PHP利用Curl实现多线程抓取网页和下载文件
PHP 利用 Curl 可以完成各种传送文件操作,比如模拟浏览器发送GET,POST请求等等,然而因为php语言本身不支持多线程,所以开发爬虫程序效率并不高,一般采集 数据可以利用 PHPquery ...
- 使用selenium webdriver+beautifulsoup+跳转frame,实现模拟点击网页下一页按钮,抓取网页数据
记录一次快速实现的python爬虫,想要抓取中财网数据引擎的新三板板块下面所有股票的公司档案,网址为http://data.cfi.cn/data_ndkA0A1934A1935A1986A1995. ...
随机推荐
- 杭电OJ1062---Text Reverse(c++)(C++库getline的使用)
Text Reverse Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Tot ...
- 2018年第九届蓝桥杯B组(201806-----递增三元组)
给定三个整数数组 A = [A1, A2, - AN], B = [B1, B2, - BN], C = [C1, C2, - CN], 请你统计有多少个三元组(i, j, k) 满足: 1 < ...
- Lesson_strange_words2
cap 大写字母 mechanical 机械的,力学的 optical 光学的,视觉的 charge 电荷,负载 couple 耦合的,联接的,成对的 charge-coupled device 电荷 ...
- 【转】借助LVS+Keepalived实现负载均衡
一.负载均衡:必不可少的基础手段 1.1 找更多的牛来拉车吧 当前大多数的互联网系统都使用了服务器集群技术,集群即将相同服务部署在多台服务器上构成一个集群整体对外提供服务,这些集群可以是Web应用服务 ...
- MATLAB OPC错误OPCenum service is not operating correctly解决办法
错误截图: 出错原因:C:\Windows\SysWOW64下没有OpcEnum.exe等文件,opc需要这些文件才能正常运行.有些系统内置了,有些系统没有. 解决方法:去opc官网https://o ...
- 【Java基础】面向对象中
面向对象中 这一章主要涉及面向对象的三大特征,包括封装.继承.多态.(抽象). 封装 程序设计追求"高内聚,低耦合": 高内聚 :类的内部数据操作细节自己完成,不允许外部干涉: 低 ...
- 【JavaWeb】Servlet 程序
Servlet 程序 Servlet Servlet 是在 Web 服务器中运行的小型 Java 程序.Servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求. ...
- ssh连接不上vmware虚拟机centos7.5
在vmware中安装centos7.5后,手动设置IP地址192.168.1.5,发现主机ping不通虚拟机的IP,以下是我的解决办法 1.vmware设置选择仅主机模式 2.在主机查看vmnet1( ...
- 克隆slave
在日常生活中,我们做的比较多的操作就是在线添加从库,比如线上有一主一丛两个数据库,由于业务的需要一台从库的读取量无法满足现在的需求,这样就需要我们在线添加从库,出于安全考虑,我们通常需要在从库上进行在 ...
- ps ww
[root@ma ~]# ps ww -p 1 PID TTY STAT TIME COMMAND 1 ? Ss 0:01 /sbin/init[root@ma ~]# ps -p 1 PID TTY ...