Skip to content

动态爬虫(二) #108

@PyxYuYu

Description

@PyxYuYu

No matter how far you may fly, never forget where you come from.

0x01 动态爬虫

  • 动态爬虫
    • 页面加载完成后,通过 Ajax 加载数据,需要 用户交互(点击、滚动等)加载数据,这些情况下就需要动态爬虫
    • 模拟用户交互:用户交互的本质,实际上就是触发了绑定在 DOM 节点的事件,所以模拟用户操作就是触发节点事件
    • 爬虫分析
      • 是否添加了新的节点(<a><iframe> 等)
      • 是否发起了新的请求(Ajax 请求跳转 等)
    • 爬虫实现
      • 获取绑定事件
        • JavaScript 中绑定事件,都会调用 addEventListener 函数,在页面代码执行前 HOOK addEventListener 函数就可以捕获到哪些 DOM 节点绑定了事件
        • 除了 addEventListener 绑定事件,还有一些 inline-script 是无法通过 HOOK addEventListener 来获取,如
          • <div id='ll' onclick="alert('dd')"></div>
      • 触发事件
        • JavaScript 中提供 dispatchEvent 函数,可以触发指定 DOM 节点的指定事件
        • onXXXX 属性可以通过遍历节点来触发
      • 获取触发事件的结果
        • 监听 DOMNodeInserted 事件来检查页面中的 DOM 是否发生变化
        • Ajax 请求的捕获
          • onResourceRequested 可以捕获非主流框架的请求,但需要通过正则匹配筛选出有效请求
          • XMLHttpRequest.openXMLHttpRequest.send 可以准确的捕获请求内容
    • 爬虫流程
      • 页面加载前,HOOK 三个接口:addEventListenerXMLHttpRequest.openXMLHttpRequest.send
      • 页面加载完后,获取所有的 <a><iframe><form> 标签,开启页面 DOM 节点监听,并触发所有的事件,最后输出结果
    • 爬虫Tips
      • 自动填写表单:应对某些情况下参数为空导致表单无法提交
      • 禁止非必要资源的加载:jpg、png、css、mp4
      • 页面加载完成后禁止跳转:防止因为触发事件导致的跳转
      • HOOK 会导致页面阻塞的函数:alertprompt
      • 触发事件向下冒泡:解决一些不标准的前端代码绑定的 DOM 节点太宽泛导致的问题,非常影响效率
  • PhantomJS
    • JavaScript 动态解析
      • PhantomJS 打开 URL 时就会利用自己的 Webkit 内核去执行 JavaScript
    • HOOK 所有的网络请求
      • PhantomJS 利用 page.onResourceRequested 方法来 HOOK 所有的网络请求
    • 静态页面分析和自动表单分析
      • PhantomJS 利用 page.evaluate 解析 JavaScript,这个执行是 沙盒式 的,它不会去执行网页外的 JavaScript 代码
    • 用户交互
      • 定义两个数组,一个用于存放分析到的链接,一个存放页面中的交互事件
      • 定义两个函数,一个获取页面全部链接,一个获取页面全部交互事件
      • 遍历所有的交互事件,每执行一个交互事件,再获取一次页面全部链接和交互事件(做去重检测)
      • 注:每执行一个交互事件,然后再获取一次页面全部链接和交互事件之前,需要等待几秒,因为如果该交互事件为 Ajax 的请求,它需要等得到服务器返回数据以后,才继续渲染页面
    • Python
      • bin 中的 phantomjs.exe 移至 python27 文件夹中的 Scripts 中就可以在 Python 代码中调用
      • 利用 Selenium 中的 webdriver 打开 PhantomJS 浏览器
         #!/usr/bin/env python
         # coding=utf-8
         
         from selenium import webdriver
         
         # 打开 PhantomJS 浏览器
         driver = webdriver.PhantomJS()
         driver.get('http://www.baidu.com')
         data = driver.page_source
         print data
         driver.quit()
      
      • 利用 driver.get 方法打开请求的 URLwebdriver 会等待页面完全加载完成之后才会返回,即程序会等待页面的所有内容加载完成,JS 渲染完毕之后才继续往下执行
        • 注:如果这里用到许多 Ajax,程序可能无法知晓是否已经完全加载完毕
      • webdriver 提供了许多寻找网页元素的方法,比如 find_element_by_* 等,也可以再加载完成后,利用 BeautifulSoup 来分析
         #!/usr/bin/env python
         # coding=utf-8
         
         from bs4 import BeautifulSoup
         from selenium import webdriver
         import time
         
         driver = webdriver.PhantomJS()
         driver.get('http://www.baidu.com')
         time.sleep(3)
         data = driver.page_source
         soup = BeautifulSoup(data, 'html.parser', from_encoding='utf-8')
         temp = html_parse.find_all('a')
         print temp
         driver.quit()
      
  • Chrome
    • headless 支持命令行下工作,看来 PhantomJS 很快就会被替代了

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions