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 相关文章推荐
MySQLdb ImportError: libmysqlclient.so.18解决方法
Aug 21 Python
python根据出生日期返回年龄的方法
Mar 26 Python
Python 创建子进程模块subprocess详解
Apr 08 Python
Python 模拟登陆的两种实现方法
Aug 10 Python
详解python中Numpy的属性与创建矩阵
Sep 10 Python
Python3调用百度AI识别图片中的文字功能示例【测试可用】
Mar 13 Python
Python2和3字符编码的区别知识点整理
Aug 08 Python
python将四元数变换为旋转矩阵的实例
Dec 04 Python
Django获取model中的字段名和字段的verbose_name方式
May 19 Python
django ObjectDoesNotExist 和 DoesNotExist的用法
Jul 09 Python
Django中的JWT身份验证的实现
May 07 Python
详解PyTorch模型保存与加载
Apr 28 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的论坛(2)
2006/10/09 PHP
PHP cdata 处理(详细介绍)
2013/07/05 PHP
护卫神php套件 php版本升级方法(php5.5.24)
2015/05/10 PHP
事件模型在各浏览器中存在差异
2010/10/20 Javascript
window.open不被拦截的实现代码
2012/08/22 Javascript
JavaScript实现的一个日期格式化函数分享
2014/12/06 Javascript
JavaScript实现倒计时代码段Item1(非常实用)
2015/11/03 Javascript
JavaScript 限制文本框不可输入英文单双引号的方法
2016/12/20 Javascript
js实现无缝滚动图
2017/02/22 Javascript
Vue 2.0学习笔记之使用$refs访问Vue中的DOM
2017/12/19 Javascript
NodeJS安装图文教程
2018/04/19 NodeJs
Vue+webpack+Element 兼容问题总结(小结)
2018/08/16 Javascript
Vue中使用 setTimeout() setInterval()函数的问题
2018/09/13 Javascript
Vue实现类似Spring官网图片滑动效果方法
2019/03/01 Javascript
记一次用vue做的活动页的方法步骤
2019/04/11 Javascript
vue滚动固定顶部及修改样式的实例代码
2019/05/30 Javascript
vue2配置scss的方法步骤
2019/06/06 Javascript
微信小程序表单验证WxValidate的使用
2019/11/27 Javascript
JS数组的常用10种方法详解
2020/05/08 Javascript
python实现的一个火车票转让信息采集器
2014/07/09 Python
python 中的int()函数怎么用
2017/10/17 Python
python如何将图片转换为字符图片
2020/08/19 Python
Django url,从一个页面调到另个页面的方法
2019/08/21 Python
windows下python安装pip方法详解
2020/02/10 Python
英国Zoro工具:手动工具,电动工具和个人防护用品
2016/11/02 全球购物
澳大利亚领先的折扣药房:Chemist Direct(有中文站)
2018/11/24 全球购物
思想品德自我鉴定
2013/10/12 职场文书
超级搞笑检讨书
2014/01/15 职场文书
就业协议书范本
2014/04/11 职场文书
经贸专业毕业生求职信范文
2014/05/01 职场文书
火灾现场处置方案
2014/05/28 职场文书
2014年幼儿园工作总结
2014/11/10 职场文书
暂住证明怎么写
2015/06/19 职场文书
关于应聘教师的自荐信
2016/01/28 职场文书
高中生物教学反思
2016/02/20 职场文书
Linux中sftp常用命令整理
2022/06/28 Servers