Selenium与PhantomJS【转】

爬虫(Spider),反爬虫(Anti-Spider),反反爬虫(Anti-Anti-Spider) 之间恢宏壮阔的斗争...

Day 1

  • 小莫想要某站上全部的电影,写了标准的爬虫(基于HttpClient库),不断地遍历某站的电影列表页面,根据 Html 分析电影名字存进本身的数据库。
  • 这个站点的运维小黎发现某个时间段请求量陡增,分析日志发现都是 IP(xxx.xxx.xxx.xxx)这个用户,而且 user-agent 仍是 Python-urllib/2.7 ,基于这两点判断非人类后直接在服务器上封杀。

Day 2

  • 小莫电影只爬了一半,因而也针对性的变换了下策略:1. user-agent 模仿百度("Baiduspider..."),2. IP每爬半个小时就换一个IP代理。
  • 小黎也发现了对应的变化,因而在服务器上设置了一个频率限制,每分钟超过120次请求的再屏蔽IP。 同时考虑到百度家的爬虫有可能会被误伤,想一想市场部门每个月几十万的投放,因而写了个脚本,经过 hostname 检查下这个 ip 是否是真的百度家的,对这些 ip 设置一个白名单。

Day 3

  • 小莫发现了新的限制后,想着我也不急着要这些数据,留给服务器慢慢爬吧,因而修改了代码,随机1-3秒爬一次,爬10次休息10秒,天天只在8-12,18-20点爬,隔几天还休息一下。
  • 小黎看着新的日志头都大了,再设定规则不当心会误伤真实用户,因而准备换了一个思路,当3个小时的总请求超过50次的时候弹出一个验证码弹框,没有准确正确输入的话就把 IP 记录进黑名单。

Day 4

  • 小莫看到验证码有些傻脸了,不过也不是没有办法,先去学习了图像识别(关键词 PIL,tesseract),再对验证码进行了二值化,分词,模式训练以后,总之最后识别了小黎的验证码(关于验证码,验证码的识别,验证码的反识别也是一个恢弘壮丽的斗争史...),以后爬虫又跑了起来。
  • 小黎是个不折不挠的好同窗,看到验证码被攻破后,和开发同窗商量了变化下开发模式,数据并再也不直接渲染,而是由前端同窗异步获取,而且经过 JavaScript 的加密库生成动态的 token,同时加密库再进行混淆(比较重要的步骤的确有网站这样作,参见淘宝和微博的登录流程)。

Day 5

  • 混淆过的加密库就没有办法了么?固然不是,能够慢慢调试,找到加密原理,不太小莫不许备用这么耗时耗力的方法,他放弃了基于 HttpClient的爬虫,选择了内置浏览器引擎的爬虫(关键词:PhantomJS,Selenium),在浏览器引擎运行页面,直接获取了正确的结果,又一次拿到了对方的数据。
  • 小黎:.....

爬虫与发爬虫的斗争还在继续...

一般状况下,在爬虫与反爬虫的对弈中,爬虫必定会胜利。javascript

换言之,只要人类可以正常访问的网页,爬虫在具有同等资源的状况下就必定能够抓取到。css

关于爬虫部分一些建议:

  1. 尽可能减小请求次数,能抓列表页就不抓详情页,减轻服务器压力,程序员都是混口饭吃不容易。
  2. 不要只看 Web 网站,还有手机 App 和 H5,这样的反爬虫措施通常比较少。
  3. 实际应用时候,通常防守方作到根据 IP 限制频次就结束了,除非很核心的数据,不会再进行更多的验证,毕竟成本的问题会考虑到。
  4. 若是真的对性能要求很高,能够考虑多线程(一些成熟的框架如 Scrapy都已支持),甚至分布式...

关于反爬虫部分的一些建议:

  • 这篇文章就够了:携程技术中心 - 携程酒店研发部研发经理崔广宇 <爬虫与反爬虫> 技术分享html

    动态HTML介绍

    JavaScript

    JavaScript 是网络上最经常使用也是支持者最多的客户端脚本语言。它能够收集 用户的跟踪数据,不须要重载页面直接提交表单,在页面嵌入多媒体文件,甚至运行网页游戏。前端

    咱们能够在网页源代码的<scripy>标签里看到,好比:java

       
       
       
       

    jQuery

    jQuery 是一个十分常见的库,70% 最流行的网站(约 200 万)和约 30% 的其余网站(约 2 亿)都在使用。一个网站使用 jQuery 的特征,就是源代码里包含了 jQuery 入口,好比:python

       
       
       
       

    若是你在一个网站上看到了 jQuery,那么采集这个网站数据的时候要格外当心。jQuery 可 以动态地建立 HTML 内容,只有在 JavaScript 代码执行以后才会显示。若是你用传统的方 法采集页面内容,就只能得到 JavaScript 代码执行以前页面上的内容。jquery

    Ajax

    咱们与网站服务器通讯的惟一方式,就是发出 HTTP 请求获取新页面。若是提交表单以后,或从服务器获取信息以后,网站的页面不须要从新刷新,那么你访问的网站就在用Ajax 技术。程序员

    Ajax 其实并非一门语言,而是用来完成网络任务(能够认为 它与网络数据采集差很少)的一系列技术。Ajax 全称是 Asynchronous JavaScript and XML(异步 JavaScript 和 XML),网站不须要使用单独的页面请求就能够和网络服务器进行交互 (收发信息)。web

    DHTML

    Ajax 同样,动态 HTML(Dynamic HTML, DHTML)也是一系列用于解决网络问题的 技术集合。DHTML 是用客户端语言改变页面的 HTML 元素(HTML、CSS,或者两者皆 被改变)。好比页面上的按钮只有当用户移动鼠标以后才出现,背景色可能每次点击都会改变,或者用一个 Ajax 请求触发页面加载一段新内容,网页是否属于DHTML,关键要看有没有用 JavaScript 控制 HTML 和 CSS 元素。数据库

    那么,如何搞定?

    那些使用了 Ajax 或 DHTML 技术改变 / 加载内容的页面,可能有一些采集手段。可是用 Python 解决这个问题只有两种途径:

    1. 直接从 JavaScript 代码里采集内容(费时费力)
    2. 用 Python 的 第三方库运行 JavaScript,直接采集你在浏览器里看到的页面(这个能够有)。

 

Selenium 与 PhantomJS

Selenium简介

Selenium是一个Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像咱们玩游戏用的按键精灵,能够按指定的命令自动操做,不一样是Selenium 能够直接运行在浏览器上,它支持全部主流的浏览器(包括PhantomJS这些无界面的浏览器)。

Selenium 能够根据咱们的指令,让浏览器自动加载页面,获取须要的数据,甚至页面截屏,或者判断网站上某些动做是否发生。

Selenium 本身不带浏览器,不支持浏览器的功能,它须要与第三方浏览器结合在一块儿才能使用。可是咱们有时候须要让它内嵌在代码中运行,因此咱们能够用一个叫 PhantomJS 的工具代替真实的浏览器。

能够从 PyPI 网站下载 Selenium库https://pypi.python.org/simple/selenium ,也能够用 第三方管理器 pip用命令安装:pip install selenium

Selenium 官方参考文档:http://selenium-python.readthedocs.io/index.html

PhantomJS简介

PhantomJS 是一个基于Webkit的“无界面”(headless)浏览器,它会把网站加载到内存并执行页面上的 JavaScript,由于不会展现图形界面,因此运行起来比完整的浏览器要高效。

若是咱们把 Selenium 和 PhantomJS 结合在一块儿,就能够运行一个很是强大的网络爬虫了,这个爬虫能够处理 JavaScrip、Cookie、headers,以及任何咱们真实用户须要作的事情。

注意:PhantomJS 只能从它的官方网站http://phantomjs.org/download.html) 下载。 由于 PhantomJS 是一个功能完善(虽然无界面)的浏览器而非一个 Python 库,因此它不须要像 Python 的其余库同样安装,但咱们能够经过Selenium调用PhantomJS来直接使用。

PhantomJS 官方参考文档:http://phantomjs.org/documentation

快速入门

Selenium 库里有个叫 WebDriver 的 API。WebDriver 有点儿像能够加载网站的浏览器,可是它也能够像 BeautifulSoup 或者其余 Selector 对象同样用来查找页面元素,与页面上的元素进行交互 (发送文本、点击等),以及执行其余动做来运行网络爬虫。

 
 
 
 

页面操做

Selenium 的 WebDriver提供了各类方法来寻找元素,假设下面有一个表单输入框:

 
 
 
 

那么:

 
 
 
 

定位UI元素 (WebElements)

关于元素的选取,有以下的API 单个元素选取
 
 
 
 
  1. By ID

       
       
       
       
    • 实现

           
           
           
           
  1. By Class Name

       
       
       
       
    • 实现

           
           
           
           
  2. By Tag Name

       
       
       
       
    • 实现

           
           
           
           
  3. By Name

       
       
       
       
    • 实现

           
           
           
           
  4. By Link Text

       
       
       
       
    • 实现

           
           
           
           
  5. By Partial Link Text

       
       
       
       
    • 实现

           
           
           
           
  6. By CSS

       
       
       
       
    • 实现

           
           
           
           
  7. By XPath

       
       
       
       
    • 实现

           
           
           
           

鼠标动做链

有些时候,咱们须要再页面上模拟一些鼠标操做,好比双击、右击、拖拽甚至按住不动等,咱们能够经过导入 ActionChains 类来作到:

示例:

 
 
 
 

填充表单

咱们已经知道了怎样向文本框中输入文字,可是有时候咱们会碰到<select> </select>标签的下拉框。直接点击下拉框中的选项不必定可行。

 
 
 
 

img

Selenium专门提供了Select类来处理下拉框。 其实 WebDriver 中提供了一个叫 Select 的方法,能够帮助咱们完成这些事情:

 
 
 
 

以上是三种选择下拉框的方式,它能够根据索引来选择,能够根据值来选择,能够根据文字来选择。注意:

  • index 索引从 0 开始
  • value是option标签的一个属性值,并非显示在下拉框中的值
  • visible_text是在option标签文本的值,是显示在下拉框的值

所有取消选择怎么办呢?很简单:

 
 
 
 

弹窗处理

当你触发了某个事件以后,页面出现了弹窗提示,处理这个提示或者获取提示信息方法以下:

 
 
 
 

页面切换

一个浏览器确定会有不少窗口,因此咱们确定要有方法来实现窗口的切换。切换窗口的方法以下:

 
 
 
 

也可使用 window_handles 方法来获取每一个窗口的操做对象。例如:

 
 
 
 

页面前进和后退

操做页面的前进和后退功能:

 
 
 
 

Cookies

获取页面每一个Cookies值,用法以下

 
 
 
 

删除Cookies,用法以下

 
 
 
 

页面等待

注意:这是很是重要的一部分!!

如今的网页愈来愈多采用了 Ajax 技术,这样程序便不能肯定什么时候某个元素彻底加载出来了。若是实际页面等待时间过长致使某个dom元素还没出来,可是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。

为了不这种元素定位困难并且会提升产生 ElementNotVisibleException 的几率。因此 Selenium 提供了两种等待方式,一种是隐式等待,一种是显式等待。

隐式等待是等待特定的时间,显式等待是指定某一条件直到这个条件成立时继续执行。

显式等待

显式等待指定某个条件,而后设置最长等待时间。若是在这个时间尚未找到元素,那么便会抛出异常了。

 
 
 
 

若是不写参数,程序默认会 0.5s 调用一次来查看元素是否已经生成,若是原本元素就是存在的,那么会当即返回。

下面是一些内置的等待条件,你能够直接调用这些条件,而不用本身写某些等待条件了。

 
 
 
 

隐式等待

隐式等待比较简单,就是简单地设置一个等待时间,单位为秒。

 
 
 
 

固然若是不设置,默认等待时间为0。

相关文章
相关标签/搜索