利用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. ...
随机推荐
- PHP 获取重复数组中 第二多的元素
$target = ["重复项目", "repeat", "repeat", "重复", "重复项目" ...
- LeetCode 二分查找模板 I
模板 #1: int binarySearch(vector<int>& nums, int target){ if(nums.size() == 0) return -1; in ...
- Java高并发与多线程(二)-----线程的实现方式
今天,我们开始Java高并发与多线程的第二篇,线程的实现方式. 通常来讲,线程有三种基础实现方式,一种是继承Thread类,一种是实现Runnable接口,还有一种是实现Callable接口,当然,如 ...
- 惠普电脑(HP PHILIPS系列)安装ubuntu后无法连接WIFI解决方案(手动安装8821CE驱动)
一步一步来, 先说环境: 我的电脑是HP PHILIPS系列,ubuntu版本是16.04 背景: win10安装ubuntu后发现无法连接wifi(但win10系统可以连接WIFI),在ubuntu ...
- CVE-2020-0796复现
今天整理资料时发现了之前存的一个cve漏洞复现过程,当时打算跟着复现来着,后来也没去复现,今天刚好有时间,所以来复现一下这个漏洞 漏洞讲解 https://www.freebuf.com/vuls/2 ...
- 爬虫-使用lxml解析html数据
使用lxml之前,我们首先要会使用XPath.利用XPath,就可以将html文档当做xml文档去进行处理解析了. 一.XPath的简单使用: XPath (XML Path Language) 是一 ...
- Python批量 png转ico
Python 批量 png 转 ico 一.前言: 首先说一下ico文件的作用:ico是windows的图标文件格式,可以用于浏览器首段图标显示,也可以用于Windows软件.我的话一般用来美化文件夹 ...
- 原生js制作表单验证,基本的表单验证方法
表单验证是web前端最常见的功能之一,也属于前端开发的基本功.自己完成一个表单验证的开发,也有助于加深对字符串处理和正则表达式的理解. 基本的表单验证包括如:字母验证.数字验证.字母和数字验证.汉字验 ...
- 使用idea插件识别log文件的相关设置
最近要读一些spring boot项目产生的log文件,众所周知,idea拥有强大的插件系统.当我打开log文件时,idea自动帮我推荐了ideolog这个插件. 但是当我安装好之后发现系统并不能完全 ...
- VMware下安装Ubantu 18.04
一.VIM安装及配置 1.安装VIM sudo apt-get install vim 二.拼音输入法以及搜狗拼音输入法安装 1.安装Fcitx输入框架 sudo apt-get install fc ...