动态爬虫(一)
PyxYuYu opened this issue · 0 comments
PyxYuYu commented
The beauty of the journey if found in the scenery along the way.
0x01 动态爬虫
Selenium
([səˈli:niəm]
)- 自动化测试工具,支持各种浏览器,包括
Chrome
、Safari
、Firefox
等主流界面式浏览器,只需要在浏览器中安装一个Selenium
插件,就可以实现Web
界面的测试 - 支持多种语言开发,如
Java
、C
、Ruby
、Python
等 - 安装
PyCharm 5
==>Project Interpreter
==>Available Packages
中搜索Selenium
安装
- 自动化测试工具,支持各种浏览器,包括
PhantomJS
([ˈfæntəm]
)- 基于
WebKit
的服务器端JavaScript API
,全面支持Web
而不需浏览器支持,是一个无界面的,可脚本编程的WebKit
浏览器引擎WebKit
:开源的浏览器引擎,也是Mac OS X
系统引擎框架版本的名称,主要用于Safari
、Dashboard
、Mail
和其他一些Mac OS X
程序
- 原生支持多种
Web
标准:DOM操作
、CSS选择器
、JSON
、Canvas
、SVG
- 应用
- 无
UI
界面的网站测试 - 屏幕快照
- 页面操作自动化
- 网络监控
- 无
- 安装
- 下载后,将
phantomjs.exe
添加至环境变量中- 我的电脑 ==> 右键属性 ==> 高级系统 ==> 高级 ==> 环境变量 ==> 系统变量 ==>
Path
中添加路径即可直接在CMD
下调用
- 我的电脑 ==> 右键属性 ==> 高级系统 ==> 高级 ==> 环境变量 ==> 系统变量 ==>
- 下载后,将
PhantomJS
提供了一个完整的REPL
环境,允许用户通过命令行与PhantomJS
进行交互,输入phantomjs
就可以进入该环境REPL
:Read Eval Print Loop
交互式编程环境
- 基础
console.log()
在终端窗口显示phantom.exit()
退出PhantomJS
环境,不管什么样的程序,exit
这一行都可少- 类似
Python
可以在REPL
环境中定义函数,也可以将函数写在js
文件中,直接调用
// REPL 环境 phantomjs> function multiply(a, b){ return a*b; } undefined phantomjs> multiply(1, 4) 4 // multiply.js 文件 function multiply(a, b){ return a*b; } console.log(multiply(1, 4)) phantom.exit() C:\Windows\System32\phantomjs multiply.js 4
webpage
模块PhantomJS
核心模块,用于网页操作
var webPage = require('webpage'); var page = webPage.create();
- 上面代码:加载
PhantomJS
的webpage
模块,并创建一个实例 - 属性及方法
open()
:用于打开具体的网页
var page = require('webpage').create(); page.open('http://www.baidu.com', function(status){ console.log(status); phantom.exit(); });
- 上面代码:接收
两个
参数- 第一个参数:网页的网址
- 第二个参数:回调函数,网页打开后该函数会运行,该函数的参数
s
是一个表示状态的字符串,如果成功打开则是success
,否则为fail
- 注:只要接收到服务器返回的结果,
PhantomJS
就会报告网页打开成功,而不管服务器是否返回404
或500
错误
- 注:只要接收到服务器返回的结果,
open()
方法默认使用的是GET
方法,与服务器通信,也可以使用其他方法POST
方法
var page = require('webpage').create(); var postBody = 'user=username&passwd=passwd'; page.open('http://www.baidu.com', 'POST', postBody, function(status){ console.log('Status:' + status); ... });
- 上面代码:使用
POST
方法向服务器发送数据,第二个参数指定HTTP
方法,第三个参数指定该方法所传输的数据
open()
方法还允许提供配置对象,对HTTP
请求进行更详细的配置
var page = require('webpage').create(); var settings = { operation: 'POST', encoding: 'utf8', headers: { 'Content-Type': 'application/json' }, data: JSON.stringify({ some: 'data', another: ['custom', 'data'] }) }; page.open('http://www.baidu.com', settings, function(status){ console.log('Status:' + status); ... });
evaluate()
:用于打开网页以后,在页面中执行JavaScript
代码
var page = require('webpage').create(); page.open('http://www.baidu.com', function(status){ var title = page.evaluate(function(){ return document.title; }); console.log('Page title is ' + title); phantom.exit(); });
- 网页内部的
console
语句,以及evaluate
方法内部的console
语句,默认不会显示在命令行,如果要显示的话,则需要利用onConsoleMessage
回调函数来监听这个事件
var page = require('webpage').create(); page.onConsoleMessage = function(msg){ console.log('Page title is ' + msg); }; page.open('http://www.baidu.com', function(status){ page.evaluate(function(){ console.log(document.title); }); phantom.exit(); });
includeJs()
:用于页面加载外部脚本,加载结束后就调用指定的回调函数
var page = require('webpage').create(); page.open('http://www.baidu.com', function(){ page.includeJs('http://path/to/jquery.min.js', function(){ page.evaluate(function(){ $('button').click(); }); phantom.exit(); }); });
- 上面代码:在页面中加载
jQuery
脚本,然后点击所有的按钮- 注:由于是异步加载,所以
phantom.exit()
语句放在page.includeJs()
方法的回调函数之中,否则页面会过早退出
- 注:由于是异步加载,所以
render()
:用于将网页保存为图片,参数就是指定的文件名,根据后缀名,可以保存为不同的格式,支持PNG GIF JPEG PDF
var page = require('webpage').create(); page.viewportSize = { width: 1920, height: 1080 }; page.open('http://www.baidu.com', function start(status){ page.render('baidu.jpeg', {format: 'jpeg', quality: '100'}); phantom.exit(); });
- 该方法还可以接受一个配置对象,
format
字段用于指定图片格式,quality
字段用于指定图片质量,最小为0
,最大为100
,必须是整数 viewportSize
、zoomFactor
属性viewportSize
:指定浏览器视口的大小,即网页加载的初始浏览器窗口大小height
字段必须指定,不可省略
zoomFactor
:指定渲染时(render
方法和renderBase64
方法)页面的放大系数,默认是1
(即100%
)
page.zoomFactor = 0.25; page.render('1.png');
onResourceRequested
属性- 用来指定一个回调函数,当页面请求一个资源时,会触发这个回调函数,第一个参数是
HTTP
请求的元数据对象,第二个参数是发出的网络请求对象
var page = require('webpage').create(); page.onResourceRequested = function(requestData, networkRequest){ console.log('Request (#' + requestData.id + '):' + JSON.stringify(requestData)); };
HTTP
请求包括以下字段id
:所请求资源的编号method
:所使用的HTTP
方法url
:所请求的资源URL
time
:一个包含请求时间的Date
对象headers
:HTTP
头信息数组
- 网络请求对象包含以下方法
abort()
:终止当前的网络请求,这会导致调用onResourceError
回调函数changeUrl(newUrl)
:改变当前网络请求的URL
setHeader(key, value)
:设置HTTP
头信息
- 用来指定一个回调函数,当页面请求一个资源时,会触发这个回调函数,第一个参数是
onResourceReceived
属性- 用于指定一个回调函数,当网页收到所请求的资源时,就会执行该回调函数,它的参数是服务器发来的
HTTP
响应的元数据对象,包含以下字段id
:所请求资源的编号url
:所请求的资源URL
time
:包含HTTP
响应时间的Date
对象headers
:响应的HTTP
头信息数组bodySize
:解压缩后的收到的内容大小contentType
:接到的内容种类redirectURL
:重定向URL
stage
:对于多数据块的HTTP
响应,头一个数据块为start
,最后一个数据块为end
status
:HTTP
状态码,成功时为200
statusText
:HTTP
状态信息,比如OK
- 如果
HTTP
响应非常大,分成多个数据块发送,onResourceReceived
会在收到每个数据块时触发回调函数 - 注:该方法收到的
response
对象是没有response.body
的具体内容的 - 可以利用正则表达式,来筛选出需要操作的一些响应资源
page.onResourceReceived = function(response){ if(mItem = response.url.match(/itemId=(\d*)/)){ itemId = parseInt(mItem[1]); } }
- 用于指定一个回调函数,当网页收到所请求的资源时,就会执行该回调函数,它的参数是服务器发来的
system
模块system
模块可以加载操作系统变量,system.args
就是参数数组,类似命令行参数
var page = require('webpage').create(), system = require('system'), t, address; // 命令行没有 address 参数,第一个参数 system.args[0] 就是 page.js if (system.args.length === 1){ console.log('Usage: page.js <url>'); phantom.exit(); } t = Date.now(); address = system.args[1]; page.open(address, function(status){ if (status !== 'success'){ console.log('Fail to load the address') } else { t = Date.now() - t; console.log('Loading time' + t + ' ms'); } phantom.exit(); });
JS
中===
和!==
===
和!==
只有在相同类型下,才会比较其值
num === str // false 类型不同,直接返回 false num !== str // true 类型不同,意味两者不等
==
和!=
比较若类型不同,先尝试转换类型,再做值的比较,最后返回值的比较结果
- 对于爬虫来说,
PhantomJS
可以实现- 静态页面链接分析
JavaScript
动态解析- 自动分析表单
HOOK
所有的网络请求
- 基于
0x02 LySRC Public Vulnerabilities
- 前天心血来潮写的一个多线程爬虫用于获取
LySRC
上的公开漏洞 - 利用
urllib.urlretrieve
下载图片,替换掉原html
中的图片保存至本地 - 代码:LySRC Public Vulnerabilities