之前我们介绍了 ajax-hook 来实现爬虫的过程中截获 Ajax 请求,可以看这篇文章如何用 Hook 实时处理和保存 Ajax 数据,在这里再另外介绍一个工具 BrowserMob Proxy,利用它我们同样可以实现 Selenium 爬虫过程中 Ajax 请求的获取。

下面我们来简单介绍一下。

BrowserMob Proxy

BrowserMob Proxy,简称 BMP,它是一个 HTTP 代理服务,利用它我们可以截获 HTTP 请求和响应内容,另外还可以把 Performance data 输出成一个 HAR 文件。

其 GitHub 链接为:https://github.com/lightbody/browsermob-proxy/。

大家可以点击进去看看详情介绍。

实际上其原理就是开了一个代理服务器,然后抓包,同时对接了 Java、Python API,以方便我们可以直接通过代码来获取到内容。

案例

官方的一些介绍比较复杂,而且大多数都是 Java 的对接,在这里我们使用 Python 来实验一下。

这里我们就直接通过一个案例来测试下吧,废话不多说。

还是拿我自己的一个测试网站为案例,链接为:https://dynamic2.scrape.center/。

页面如图所示:

其数据都是通过 Ajax 加载的,同时带着一些加密参数:

这个网站通过 Selenium 爬的话一点问题也没有,但是由于数据本身就是从 Ajax 加载的,所以如果能直接截获 Ajax 请求的话,连页面解析都省了。

所以这里我们要利用 BrowserMob Proxy 来截获一下试试。

代码实现

要用 Python 实现,我们需要先安装一个 BrowserMob Proxy 的包,命令如下:

pip3 install browsermob-proxy

另外我们还需要下载 browsermob-proxy 的二进制文件,以便于启动 BrowserMob Proxy。

下载的地址见:https://github.com/lightbody/browsermob-proxy/releases

直接下载 build 过的版本即可:

比如这里我就下载 browsermob-proxy-2.1.4.zip 文件,直接放到我的项目目录下。

好,接着呢,我们就可以实现如下代码:


from browsermobproxy import Server
import time
from selenium import webdriver
from selenium.webdriver.chrome.options import Options# 启动代理
server = Server('./browsermob-proxy-2.1.4/bin/browsermob-proxy')
server.start()
proxy = server.create_proxy()
print('proxy', proxy.proxy)# 启动浏览器
chrome_options = Options()
chrome_options.add_argument('--ignore-certificate-errors')
chrome_options.add_argument('--proxy-server={0}'.format(proxy.proxy))
driver = webdriver.Chrome(options=chrome_options)# 监听结果
base_url = 'https://dynamic2.scrape.center/'
proxy.new_har(options={'captureContent': True,'captureHeaders': True
})
driver.get(base_url)
time.sleep(3)# 读取结果
result = proxy.har
for entry in result['log']['entries']:print(entry['request']['url'])print(entry['response']['content'])

在这里呢,一共分了四步:

  • 第一步便是启动 BrowserMob Proxy,它会在本地启动一个代理服务,这里注意 Server 的第一个参数需要指定 BrowserMob Proxy 的可执行文件路径,这里我就指定了下载下来的 BrowserMob Proxy 的 bin 目录的 browsermob-proxy 的路径。
  • 第二步便是启动 Selenium 了,它可以设置 Proxy Server 为 BrowserMob Proxy 的地址。
  • 第三步便是访问页面同时监听结果,这里我们需要调用 new_har 方法,同时指定捕获 Resopnse Body 和 Headers 信息,紧接着调用 Selenium 的 get 方法访问一个页面,这时候浏览器便会加载这个页面,同时所有的请求和响应信息都会被记录到 HAR 中。
  • 第四步便是读取 HAR 到内容了,我们调用 log 到 entries 字段,里面便包含了请求和响应的具体结果,这样所有的请求和响应信息我们便能获取到了,Ajax 的内容也不在话下。

运行结果类似如下:

这里可以看到所有的数据都能获取到了,包括 Ajax 结果、JavaScript、CSS 文件内容等等。

这里 har 的内容其实是一个 JSON 对象,里面记录了在访问页面的过程中发生的所有请求和响应内容,一般内容都会记录在 logs 的 entries 字段里面,还有其他的信息如有需要也可以读取。

所以,这样我们就能从 Selenium 中获取 Ajax 请求内容了。

优化

不过像上面这种代码还是不方便啊,不好复用,不好扩展,我们来稍微改写下,代码如下:


from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from browsermobproxy import Server
import time
import jsonclass BaseFramework(object):def __init__(self):self.server = Server('./browsermob-proxy-2.1.4/bin/browsermob-proxy')self.server.start()self.proxy = self.server.create_proxy()chrome_options = Options()chrome_options.add_argument('--ignore-certificate-errors')chrome_options.add_argument('--proxy-server={0}'.format(self.proxy.proxy))self.browser = webdriver.Chrome(options=chrome_options)def process_request(self, request, response):passdef process_response(self, response, request):passdef run(self, func, *args):self.proxy.new_har(options={'captureContent': True,'captureHeaders': True})func(*args)result = self.proxy.harfor entry in result['log']['entries']:request = entry['request']response = entry['response']self.process_request(request, response)self.process_response(response, request)def __del__(self):self.proxy.close()self.browser.close()class MovieFramework(BaseFramework):def process_request(self, request, response):print(request)def process_response(self, response, request):if '/api/movie/' in request['url']:print(response['content'])text = response['content']['text']results = json.loads(text)['results']for item in results:name = item.get('name')with open(f'{name}.json', 'w', encoding='utf-8') as f:json.dump(item, f, ensure_ascii=False, indent=2)def load(self, url):self.browser.get(url)time.sleep(3)if __name__ == '__main__':f = MovieFramework()for page in range(1, 5):url = f'https://dynamic2.scrape.center/page/{page}'f.run(f.load, url)

这里框架写的很基础,还有很多需要完善的地方,就只借着这雏形说说大体思路:

  • 这里我先定义了一个 BaseFramework,就是基础框架,然后里面定义了几个关键方法,__init__ 方法不多说了,就是把一些初始化的工作放进去。然后定义了 run 方法,把 HAR 的声明、访问、读取的操作封装了一下。然后定义了 process_response 和 process_request 的回调,这里就没实现任何操作,可以在子类实现。
  • 如果我们要写一个爬虫的话,可以新建一个子类来继承刚才定义的 BaseFramework,然后可以自己实现 process_request 和 process_response 来处理请求和响应的结果,比如这里我就实现了一个 MovieFramework,然后实现了 process_response 处理响应信息,里面判断了 Ajax 请求的 URL,然后进行了提取和保存处理。里面 load 方法就是自行定义的,里面正常定义逻辑即可。
  • 最后运行的时候使用 run 方法运行自定义的 load 方法即可,传入 load 方法的参数,即可完成页面的加载。同时加载的过程中 process_response 方法就会被回调,对结果进行处理。这里我们就提取了 Ajax 数据,然后保存下来了。

最终运行下,我们就可以看到一条条的电影数据就被保存下来了,如图所示:

是不是方便多了?有了它我们连页面解析的那一步都直接省略了,直接拿到了原始 Ajax 数据,舒服。

当然上面的框架还有很多很多需要优化的地方,大家可以参考思路自己实现。

总结

本节我们就讲解了利用 BrowserMob Proxy 来截获和处理 Ajax 数据的方法,实现简单方便。有了这个我们就不需要非得等页面加载出来之后再根据页面渲染结果提取信息了,Ajax 请求直接拿原始数据,爽歪歪!

点击这里,了解更多精彩内容

教你轻松截获 Selenium 中的 Ajax 数据相关推荐

  1. 教你轻松修改PPT中剪贴画颜色

    转载者: 智能变电站ppt课件              来源: www.2ppt.cn 在制作演示文稿时,为了达到满意的效果我们经常会插入漂亮的剪贴画.但有时起到的效果会相反,因为剪贴画是程序自带的 ...

  2. 教你轻松分清pandas中的axis=0,axis=1具体含义

    在学习Pandas的过程中碰到里面有一些函数都包含了axis这个参数,但是这参数包含两个值0和1,而且0和1代表不同的含义,这也让我学的有点懵逼,于是网上查阅了一些相关资料把学习心得记录下来. 以下面 ...

  3. 一招教你轻松从图像中裁剪出婚纱礼服和面纱

    Super PhotoCut Pro是一款简单粗暴的抠图软件,它能够准确地覆盖你想要去除的任何一个细节区域,抠出图片中你最想要的部分,不需要任何的技巧,那么photocut怎么用呢?你只需要在图片上勾 ...

  4. java struts2 ajax_在struts2的Action中返回Ajax数据

    author:z_xiaofei168 如何在struts2的action中返回数据(普通字符串.图片)给ajax核心中的XMLHttpRequest对象. 今天下午做项目,就是用户注册是时候,登录名 ...

  5. python中selenium中使用ajax_selenium 智能等待ajax完成调用

    selenium 智能等待ajax完成调用 使用webdriverwater 传入一个lambda表达式 判断 ajax调用转台 当 jquery.active==0 表示ajax调用完成 仅在jqu ...

  6. python中selenium中使用ajax_Selenium测试Ajax程序(转)

    上周末参加了Qclub的百度技术沙龙,听了百度的孙景卫讲了Web自动化测试,讲的非常好,然后在小组讨论时又有幸座在了一起.我们讨论的一个内容,就是Ajax应用程序比原来的非Ajax程序更不易测试,这里 ...

  7. ppt中如何合并流程图_简单4招,教你轻松搞定PPT中的流程图!

    原标题:简单4招,教你轻松搞定PPT中的流程图! 来自:PK阿锴(ID:akaippt) 作者:王培锴 今天跟大家分享PPT流程图的制作方法,流程图相信大家都经常遇到,通常分布着许多节点,由线条链接起 ...

  8. 如何在原先的jqgrid中填充新的数据_自然人电子税务局(扣缴端)数据如何恢复?申税小微教您轻松搞定...

    自然人电子税务局 数据如何恢复? 申税小微教您轻松搞定! 财务小王:申税小微,我们公司换了新电脑,重新安装的自然人电子税务局(扣缴端)上没有人员采集信息和历史申报数据该怎么办? 申税小微: 1.可以在 ...

  9. 一步步教你轻松学朴素贝叶斯模型算法理论篇1

    一步步教你轻松学朴素贝叶斯模型理论篇1 (白宁超2018年9月3日17:51:32) 导读:朴素贝叶斯模型是机器学习常用的模型算法之一,其在文本分类方面简单易行,且取得不错的分类效果.所以很受欢迎,对 ...

最新文章

  1. 《算法的乐趣》----第二章算法设计基础(笔记一)
  2. android udp 收发例子_如何利用光衰减器来测试光纤收发器的灵敏度?
  3. mybatis的执行流程
  4. DiscuzX2.5视频教程
  5. Python 的数据类型
  6. Orchard Core一分钟搭建ASP.NET Core CMS
  7. NVLink技术及影响解析
  8. 浙江省工程师职称英语和计算机考试报名,浙江省工程师职称英语免考条件
  9. taro更新页面数据_Taro 全局数据状态管理
  10. caffe的python接口学习(3):训练模型(training)
  11. Spring事件监听机制
  12. http文件下载c/c++ 多种方法
  13. Vue组件化|通用组件开发——Notification通知组件
  14. 任正非:华为留不住人才是我的痛!
  15. 密码正确登入不了网络计算机,windows远程登录密码正确但登录不上
  16. Excel显示公式栏/编辑栏
  17. 米 html像素转换,字体磅、像素、厘米转换
  18. 成功解决ValueError: pos_label=1 is not a valid label: array([‘0‘, ‘1‘], dtype=‘<U1‘)
  19. python等于号前后一定要加空格吗_英语标点前后要加空格吗?
  20. java中的算法(一致性hash算法和数据结构的问题)

热门文章

  1. es6 Object.getOwnPropertyDescriptors()
  2. centos安装python2.7.2_Centos6.2 安装Python2.7.x 版本
  3. python scapy模块安装_python scapy模块安装与依赖模块
  4. 炸掉卡西欧991CNX
  5. c++ 中变量成员的初始化时机
  6. python第九十一天----第十六周作业
  7. 搭建Android开发环境 第二章
  8. 使用MegaCli工具,在线调整raid配置
  9. Unity脚本各种[XXX]的用法
  10. MyEclipse6.5注册码(转)