selenium在执行phantomjs的API并获取执行结果的方法


Posted in Python onDecember 17, 2018

前言

因为最近要写一个抓取sitemap和相应的参数的小脚本,现有的爬虫无论用什么语言写的,几乎都无法抓取参数,所以我思考了一下,先做一个简单的总结。

本来以为写个这种sitemap的爬虫很简单,经过思考之后才发现其中的可怕之处,最关键的是参数的提取,这个太麻烦了。。。这个时候才发现AWVS的无敌和强大之处。。。

如果我们要获取网站的sitemap同时还要抓取对应链接的参数,我大概总结了url的几个来源:

1、页面上直接现有的form表单以及现有的href等指向的链接及参数,这个相对比较简单,不过要考虑post和get的问题。

2、由js生成的DOM中的form表单和href指向的链接

3、由js发起的访问请求,例如AJAX请求等

4、通过点击然后调用js发送请求,或是点击生成一个form或是生产一个DOM,然后再点击再由js发送请求。例如如下代码

<div>
 <input id="searchTitle" name="searchTitle" value="" type="text">
 <div class="button" onclick="javascript:searchWeb();"></div>
 </div>

5、通过setTimeout函数延迟触发的js的请求,例如setTimeout("request()", 2000);,这一类我暂时还没有太好的办法解决,不过有初步的办法,后面会说到。

目前我大概想到这么五类,肯定还有没考虑到的地方,并且目前实际的代码还没有写出来,我先记录一下我的想法,要是有哪位师傅有兴趣请务必联系我。。。。orz。。

要解决上述的5个问题,因为我的工程的前半部分使用python写的,所以这里我需要用python来解决,那么最佳选择必然是selenium和phantomjs,其实比起来我更想用原生的phantomjs来写。

用phantomjs的话第一个和第二个问题不攻自破,直接正则匹配下来就行了,因为它会帮我们先把页面的js执行了。

第三个问题也相对比较好解决,我们通过原生phantomjs的APIonResourceRequested就能够监控所有从页面发出去的请求。

然后再来看第四个问题,我目前的想法应该没有办法彻底解决,我们同样可以用phantomjs向页面的所有的dom发送一个click事件,但是这样子的话时间是一个很大的问题,所以初步想法向所有具有onclick事件的标签发送点击事件

然后再来看第五个问题,这应该是最麻烦的一个,我初步的想法还是用onResourceRequested事件,然后设置一个超时时限,让页面执行个几秒钟,但是最后我还是放弃了这个想法,我决定忽视这个问题,因为如果每个页面都等上几秒那时间耗费不堆上天了。

以上就是我目前初步的一些思考,还有很多不成熟之处。

selenium与phantomjs联动的问题

之前一直知道有selenium这个东西,不够因为没有地方需要,也没有可以去学习,不过对phantomjs可能会稍微熟悉一些。

先写个简单的程序

from selenium import webdriver
service_args=[]
service_args.append('--load-images=no') ##关闭图片加载
service_args.append('--disk-cache=yes') ##开启缓存
service_args.append('--ignore-ssl-errors=true') ##忽略https错误

d=webdriver.PhantomJS("phantomjs",service_args=service_args)
d.get("http://xxxxxxxxxxxxxxxxxxxxx")
print d.page_source
d.quit()

这样就可以发送get请求了。

问题一:没有post请求?

我觉得应该是我还了解的不够。不过翻了API,确实没有找到,希望大家能够指出我的错误,但我真的好像没有找到能够发送post请求的地方,真是蠢爆了。。

这里我想到了两种方法解决,先说一种,第二种留到后面说。

就是用requests库递交post请求,拿下来的cookie,调用add_cookie函数给它,然后让它带着cookie发送get请求就好了。

样例如下

from selenium import webdriver
import requests
r=requests.session()

service_args=[]
service_args.append('--load-images=no') ##关闭图片加载
service_args.append('--disk-cache=yes') ##开启缓存
service_args.append('--ignore-ssl-errors=true') ##忽略https错误

d=webdriver.PhantomJS("phantomjs",service_args=service_args)

data={
 "username":"123",
 "password":"123",
 "login":"1"
 }

result=r.post("http://127.0.0.1:8000/web/login.php",data=data)
cookies=r.cookies.get_dict()
for i in cookies:
 d.add_cookie({
 'name': i,
 'value' :cookies[i],
 'path':'/',
 'domain':'127.0.0.1'
  })
d.get("http://127.0.0.1:8000/web/index.php")
print d.page_source
d.quit()

另外这个add_cookie函数还比较刁钻,还要把path和domain都设置好,不然有时会报错。

第二个方法的话,我们知道,如果用原生PhantomJS的话,我们可以很容易递交post请求,比如如下:

var webPage = require('webpage');
var page = webPage.create();

var settings = {
 operation: "POST",
 header:{},
 data: "username=123&password=123&login=1"
};
page.open('http://127.0.0.1:8000/web/login.php', settings, function(status) {
 //console.log(page.content);
 for(var i=0;i<page.cookies.length;i++){
 console.log(page.cookies[i].name+":"+page.cookies[i].value)
 }
});

所以我们想办法就是直接在 Selenium中让PhantomJS 执行它的 API就可以了,这里不贴了,看完下一小节就知道怎么写了。

问题二:在 Selenium中获取PhantomJS 的API的执行结果?

还好Selenium带了个get_log函数,比如我监控'http://127.0.0.1:8000/web/index.php‘页面向外发送的所有请求,如果用原生的phantomjs,很好办,如下:

var webPage = require('webpage');
var page = webPage.create();

page.onResourceRequested = function (request) {
 console.log('Request ' + request.url);
};
...........
...........

所以我们直接在Selenium中调用PhantomJS 的API就好了。如下

from selenium import webdriver
import requests
r=requests.session()

service_args=[]
service_args.append('--load-images=no') ##关闭图片加载
service_args.append('--disk-cache=yes') ##开启缓存
service_args.append('--ignore-ssl-errors=true') ##忽略https错误

d=webdriver.PhantomJS("phantomjs",service_args=service_args)

data={
 "username":"123",
 "password":"123",
 "login":"1"
 }

result=r.post("http://127.0.0.1:8000/web/login.php",data=data)
cookies=r.cookies.get_dict()
for i in cookies:
 d.add_cookie({
 'name': i,
 'value' :cookies[i],
 'path':'/',
 'domain':'127.0.0.1'
  })
script = "var page=this;page.onResourceRequested = function (request){console.log(request.url);};"
d.command_executor._commands['executePhantomScript'] = ('POST', '/session/$sessionId/phantom/execute')
d.execute('executePhantomScript', {'script': script, 'args': []})

d.get("http://127.0.0.1:8000/web/index.php")
print d.page_source
d.quit()

这里上述代码确实能够实时执行,但是就这样写的话没有办法获取到结果。

这里需要用到一个get_log函数,改进如下:

from selenium import webdriver
import requests
r=requests.session()

service_args=[]
service_args.append('--load-images=no') ##关闭图片加载
service_args.append('--disk-cache=yes') ##开启缓存
service_args.append('--ignore-ssl-errors=true') ##忽略https错误

d=webdriver.PhantomJS("phantomjs",service_args=service_args)

data={
 "username":"123",
 "password":"123",
 "login":"1"
 }

result=r.post("http://127.0.0.1:8000/web/login.php",data=data)
cookies=r.cookies.get_dict()
for i in cookies:
 d.add_cookie({
 'name': i,
 'value' :cookies[i],
 'path':'/',
 'domain':'127.0.0.1'
  })
script = "var page=this;page.onResourceRequested = function (request){page.browserLog.push(request.url);};"
d.command_executor._commands['executePhantomScript'] = ('POST', '/session/$sessionId/phantom/execute')
d.execute('executePhantomScript', {'script': script, 'args': []})

d.get("http://127.0.0.1:8000/web/index.php")
print d.page_source
print d.get_log('browser')
d.quit()

在js脚本中我们调用page.browserLog.push,然后在python脚本中我们get_log('browser')去获取就可以实现相互沟通,当然肯定还有别的办法,不过我没有找到。。。。僵硬了。。。。

后记

再说这个抓取sitemap和请求参数的小脚本,想了想还是觉得非常麻烦,虽然几个问题都有了相应的解决办法,也不管好坏,加上今天稍微研究了一下python调用phantom的优化,还是稍微有点信心了,但是感觉要整合到一起来还是会很麻烦,效率问题是一个,能否真正准确抓取完整又是另一个,慢慢来把,没想到最初觉得不是问题的问题最后却成了我最大的麻烦之一。。僵硬。。。最后还要说的是原声的phantomjs真的比selenium去调用舒服得多。。。现在想来要是最开始想把每个环节思考一下就好了,要是思考了大概就不会用python了,大概会用nodejs,对了,最近稍微研究了一下nodejs的一些渗透和攻击方法,后续整理一下分享出来,希望师傅们能够帮忙指点指点。

以上这篇selenium在执行phantomjs的API并获取执行结果的方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
详细介绍Python中的偏函数
Apr 27 Python
使用Python生成随机密码的示例分享
Feb 18 Python
python正则表达式之作业计算器
Mar 18 Python
Python实现HTTP协议下的文件下载方法总结
Apr 20 Python
Python实现的概率分布运算操作示例
Aug 14 Python
[原创]Python入门教程2. 字符串基本操作【运算、格式化输出、常用函数】
Oct 29 Python
详解Python的循环结构知识点
May 20 Python
Python facenet进行人脸识别测试过程解析
Aug 16 Python
关于Python核心框架tornado的异步协程的2种方法详解
Aug 28 Python
Python跑循环时内存泄露的解决方法
Jan 13 Python
Python多线程thread及模块使用实例
Apr 28 Python
python正则表达式 匹配反斜杠的操作方法
Aug 07 Python
Python脚本完成post接口测试的实例
Dec 17 #Python
python:接口间数据传递与调用方法
Dec 17 #Python
python直接获取API传递回来的参数方法
Dec 17 #Python
python获取url的返回信息方法
Dec 17 #Python
Pycharm配置远程调试的方法步骤
Dec 17 #Python
Python解析、提取url关键字的实例详解
Dec 17 #Python
Django Rest framework之认证的实现代码
Dec 17 #Python
You might like
解析mysql left( right ) join使用on与where筛选的差异
2013/06/18 PHP
PHP URL参数获取方式的四种例子
2014/02/28 PHP
php readfile下载大文件失败的解决方法
2017/05/22 PHP
详解阿里云视频直播PHP-SDK接入教程
2020/07/09 PHP
js克隆对象、数组的常用方法介绍
2013/09/26 Javascript
JavaScript数组常用操作技巧汇总
2014/11/17 Javascript
JavaScript 学习笔记之语句
2015/01/14 Javascript
jQuery获取字符串中出现最多的数
2016/02/22 Javascript
基于javascript实现图片滑动效果
2016/05/07 Javascript
详解nodejs爬虫程序解决gbk等中文编码问题
2017/04/06 NodeJs
详解Vue项目中实现锚点定位
2019/04/24 Javascript
小程序最新获取用户昵称和头像的方法总结
2019/09/23 Javascript
深入学习Vue nextTick的用法及原理
2019/10/08 Javascript
Vue 一键清空表单的实现方法
2020/02/07 Javascript
微信小程序开发(二):页面跳转并传参操作示例
2020/06/01 Javascript
vue+element获取el-table某行的下标,根据下标操作数组对象方式
2020/08/07 Javascript
原生js中运算符及流程控制示例详解
2021/01/05 Javascript
[06:20]2015国际邀请赛第三日top10
2015/08/08 DOTA
[05:37]DOTA2-DPC中国联赛 正赛 Elephant vs iG 选手采访
2021/03/11 DOTA
Python 数据结构之队列的实现
2017/01/22 Python
python最小生成树kruskal与prim算法详解
2019/01/17 Python
Python3转换html到pdf的不同解决方案
2019/03/11 Python
Python一键查找iOS项目中未使用的图片、音频、视频资源
2019/08/12 Python
python针对mysql数据库的连接、查询、更新、删除操作示例
2019/09/11 Python
Python无头爬虫下载文件的实现
2020/04/02 Python
sklearn的predict_proba使用说明
2020/06/28 Python
Urban Outfitters德国官网:美国跨国生活方式零售公司
2018/05/21 全球购物
德国滑雪和户外用品网上商店:XSPO
2019/10/30 全球购物
水产养殖学应届生求职信
2013/09/29 职场文书
函授大专自我鉴定
2013/11/01 职场文书
党员十八大心得体会
2014/09/12 职场文书
幼儿教师2014年度工作总结
2014/12/16 职场文书
确保减税降费落地生根,用实实在在措施
2019/07/19 职场文书
MySQL慢查询的坑
2021/04/28 MySQL
Axios取消重复请求的方法实例详解
2021/06/15 Javascript
Python基础教程,Python入门教程(超详细)
2021/06/24 Python