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实现监控linux性能及进程消耗性能的方法
Jul 25 Python
Python 迭代器工具包【推荐】
May 06 Python
Python使用PDFMiner解析PDF代码实例
Mar 27 Python
深入探究Django中的Session与Cookie
Jul 30 Python
Python实现多属性排序的方法
Dec 05 Python
Python如何调用外部系统命令
Aug 07 Python
解决python多行注释引发缩进错误的问题
Aug 23 Python
python3 实现爬取TOP500的音乐信息并存储到mongoDB数据库中
Aug 24 Python
Python unittest工作原理和使用过程解析
Feb 24 Python
keras中的backend.clip用法
May 22 Python
python中二分查找法的实现方法
Dec 06 Python
PyCharm2020.3.2安装超详细教程
Feb 08 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
追忆往昔!浅谈收音机的百年发展历史
2021/03/01 无线电
php cc攻击代码与防范方法
2012/10/18 PHP
linux系统下php安装mbstring扩展的二种方法
2014/01/20 PHP
PHP实现手机号码中间四位用星号(*)隐藏的自定义函数分享
2014/09/27 PHP
PHP在线调试执行的实现方法(附demo源码)
2016/04/28 PHP
yii2使用GridView实现数据全选及批量删除按钮示例
2017/03/01 PHP
ExtJS4中的requires使用方法示例介绍
2013/12/03 Javascript
javascript模拟命名空间
2015/04/17 Javascript
jquery序列化方法实例分析
2015/06/10 Javascript
jquery实现文本框textarea自适应高度
2016/03/09 Javascript
Jquery on方法绑定事件后执行多次的解决方法
2016/06/02 Javascript
javascript this详细介绍
2016/09/19 Javascript
web打印小结
2017/01/11 Javascript
jQuery命名空间与闭包用法示例
2017/01/12 Javascript
Angular 开发学习之Angular CLI的安装使用
2017/12/31 Javascript
JavaScript简单实现的仿微博留言功能示例
2019/01/17 Javascript
使用webpack4编译并压缩ES6代码的方法示例
2019/04/24 Javascript
[45:16]完美世界DOTA2联赛PWL S3 Magma vs Phoenix 第一场 12.12
2020/12/16 DOTA
使用PyCharm配合部署Python的Django框架的配置纪实
2015/11/19 Python
Python 的描述符 descriptor详解
2016/02/27 Python
Python制作Windows系统服务
2017/03/25 Python
Tensorflow之构建自己的图片数据集TFrecords的方法
2018/02/07 Python
python实现读Excel写入.txt的方法
2018/04/29 Python
django2+uwsgi+nginx上线部署到服务器Ubuntu16.04
2018/06/26 Python
django query模块
2019/04/20 Python
django将数组传递给前台模板的方法
2019/08/06 Python
opencv3/C++图像像素操作详解
2019/12/10 Python
Python JSON常用编解码方法代码实例
2020/09/05 Python
PyCharm Community安装与配置的详细教程
2020/11/24 Python
python 发送邮件的四种方法汇总
2020/12/02 Python
乳制品整治工作方案
2014/05/29 职场文书
小学网上祭英烈活动总结
2014/07/05 职场文书
山东省召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
ConstraintValidator类如何实现自定义注解校验前端传参
2021/06/18 Java/Android
React如何创建组件
2021/06/27 Javascript
vue如何实现关闭对话框后刷新列表
2022/04/08 Vue.js