PyxYuYu/MyBlog

动态爬虫(一)

PyxYuYu opened this issue · 0 comments

The beauty of the journey if found in the scenery along the way.

0x01 动态爬虫

  • Selenium[səˈli:niəm]
    • 自动化测试工具,支持各种浏览器,包括 ChromeSafariFirefox 等主流界面式浏览器,只需要在浏览器中安装一个 Selenium 插件,就可以实现 Web 界面的测试
    • 支持多种语言开发,如 JavaCRubyPython
    • 安装
      • PyCharm 5 ==> Project Interpreter ==> Available Packages 中搜索 Selenium 安装
  • PhantomJS[ˈfæntəm]
    • 基于 WebKit 的服务器端 JavaScript API,全面支持 Web 而不需浏览器支持,是一个无界面的,可脚本编程的 WebKit 浏览器引擎
      • WebKit:开源的浏览器引擎,也是 Mac OS X 系统引擎框架版本的名称,主要用于 SafariDashboardMail 和其他一些 Mac OS X 程序
    • 原生支持多种 Web 标准: DOM操作CSS选择器JSONCanvasSVG
    • 应用
      • UI 界面的网站测试
      • 屏幕快照
      • 页面操作自动化
      • 网络监控
    • 安装
      • 下载后,将 phantomjs.exe 添加至环境变量中
        • 我的电脑 ==> 右键属性 ==> 高级系统 ==> 高级 ==> 环境变量 ==> 系统变量 ==> Path 中添加路径即可直接在 CMD 下调用
    • PhantomJS 提供了一个完整的 REPL 环境,允许用户通过命令行与 PhantomJS 进行交互,输入 phantomjs 就可以进入该环境
      • REPLRead 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();
      
      • 上面代码:加载 PhantomJSwebpage 模块,并创建一个实例
      • 属性及方法
        • open():用于打开具体的网页
           var page = require('webpage').create();
           page.open('http://www.baidu.com', function(status){
               console.log(status);
          	 phantom.exit();
           });
        
        • 上面代码:接收 两个 参数
          • 第一个参数:网页的网址
          • 第二个参数:回调函数,网页打开后该函数会运行,该函数的参数 s 是一个表示状态的字符串,如果成功打开则是 success,否则为 fail
            • 注:只要接收到服务器返回的结果,PhantomJS 就会报告网页打开成功,而不管服务器是否返回 404500 错误
        • 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,必须是整数
        • viewportSizezoomFactor 属性
          • 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 对象
            • headersHTTP 头信息数组
          • 网络请求对象包含以下方法
            • 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
            • statusHTTP 状态码,成功时为 200
            • statusTextHTTP 状态信息,比如 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