0×00 前言
如果读者读过我前面的关于爬虫的文章,应该大概都清楚我们现在可以对一个静态的web页面”为所欲为“了,但是技术的发展总是没有止境的,仅仅是这样对静态页面处理远远不够,要知道现在很多的web页面有意无意为了防止静态爬虫使用ajax技术动态加载页面,这就导致了在面对这些网站的时候,我们前面的技术并不能起到什么很好的效果,所以,我在本系列文章开头就说了会提供动态加载网页的解决方案,在这篇文章里,笔者就在这里提出这个解决方案,用来解决以前我们没有办法的问题。
本人对于Python学习创建了一个小小的学习圈子,为各位提供了一个平台,大家一起来讨论学习Python。欢迎各位到来Python学习群:960410445一起讨论视频分享学习。Python是未来的发展方向,正在挑战我们的分析能力及对世界的认知方式,因此,我们与时俱进,迎接变化,并不断的成长,掌握Python核心技术,才是掌握真正的价值所在。
0×01 动态页面解决方案Selenium+PhantomJS
Python2(或Python3) 本文使用Python2.7.11
Selenium 自动化web测试解决方案
PhantomJS 一个没有图形界面的浏览器
0×02 原理回顾对比
讨论:讲selenium自动化测试技术应用于爬虫数据挖掘,其实我也是经历了一段时间的思考,有一些基础的朋友们可能会知道,BeautifulSoup这种完全基于静态的web页面分析是没有办法执行JS的,但是我们在使用web的过程中,基本不可能不用到JS脚本,当时我就想寻找一个JS引擎整合BeautifulSoup,然后计划使用Spidermonkey这个技术,如果需要这么做的话,我们会发现,我们不仅要用BeautifulSoup爬取页面的目标元素,而且还要考虑爬取JS脚本,在执行这些js脚本后,我们还需要再次分析这些脚本返回的数据或者是对HTML页面产生的影响,我觉得这样加大了太多的不确定因素,我们不想花太多的时间放在脚本编写上,既然选用Python,就要发挥它的巨大Pythonic的优势。然后还有一个解决方案就是 Ghost.py,github主页。我想也许我们通过这个方案介绍的不仅仅是爬虫,也可能是一个新世界的大门,所以我还是选择selenium吧,web自动化测试的一整套解决方案。
其实我们从BeautifulSoup的解决方案过度到selenium的方案就是一个思维上的“退步“的过程,从直接HTML解析->分析JS->webkit->索性直接用headless浏览器来操作web页面的selenium。
所以也就是说,我们接下来要讨论的selenium用于爬虫和以前学习的静态页面处理有着本质的区别,可以认为对我们来说是一个全新的技术。
0×03 Quick Start
在这里我们首先可以很负责任的说,通过以下的例子并不会让读者完全掌握selenium的使用,但是通过动手,大家可以了解到selenium是非常好用并且并不输于BeautifulSoup的(也许这两个并不是一个级别并不能比较)。但是可以说BeautifulSoup中的定位元素,在selenium中都可以做到,而且Selenium可以设置等待时间让页面完成加载,或者设置条件让web页面加载出我们所需要的数据然后再获取数据。
下载与安装:
首先我们需要下载要给PhantomJS浏览器from官网。
然后安装selenium,使用easy_install或者pip都可以很方便的安装:
1.easy_install selenium
2.pip install selenium
然后我们的第一个目标页面http://pythonscraping.com/pages/javascript/ajaxDemo.html很简单,就是一个存在ajax的情况:页面如下:
Some JavaScript-loaded contentThis is some content that will appear on the page while it's loading. You don't care about scraping this.$.ajax({ type:"GET", url:"loadedContent.php", success:function(response){ setTimeout(function(){ $('#content').html(response); },2000); } });functionajax_delay(str){ setTimeout("str",2000);}
我们简单看到这个web页面是使用ajax动态加载数据,GET请求LoadedContent.php然后把结果直接显示在content里。对于这样的方式我们并不需要太深入了解,总之我们只需要知道我们如果使用传统的方式获取,得到的就是上面的静态html而没有loadedContent.php中的内容。
作为selenium的爬虫应用quickstart,我们没必要太深入讲解原理,我们需要把PhantomJS和python脚本放在同一个文件夹下,建立selenium_test.py文件夹
然后输入selenium_test.py中的内容:
#引入selenium中的webdriverfrom selenium import webdriverimporttime#webdriver中的PhantomJS方法可以打开一个我们下载的静默浏览器。#输入executable_path为当前文件夹下的phantomjs.exe以启动浏览器driver =webdriver.PhantomJS(executable_path="phantomjs.exe")#使用浏览器请求页面driver.get("http://pythonscraping.com/pages/javascript/ajaxDemo.html")#加载3秒,等待所有数据加载完毕time.sleep(3)#通过id来定位元素,#.text获取元素的文本数据printdriver.find_element_by_id('content').text#关闭浏览器driver.close()
建议大家先用传统的方法尝试一下这个页面,再使用上面的脚本来执行。观察两个结果有什么不同。当然,我这里明确说明:如果大家真的不想再学习selenium的定位元素,发送数据等操作了,其实也是没什么问题的。通过一个叫page_source的属性,我们完全可以获取当前整个页面的和html,然后再把页面传给BeautifulSoup,这样我们仍然可以使用BeautifulSoup进行解析。
0×04 Webdriver API
我们发现要使用selenium分析页面,导入的是webdriver,webdriver有很多易用的API:
定位元素,控制浏览器行为,刷新,web元素操作,模拟键盘鼠标事件,获得验证信息,设置等待时间,上传下载文件,调用javascript,窗口截图。
我们写简单的爬虫可能要用得到的就是元素定位和设置等待时间,笔者在这里利用这两个特性再写一个例子供大家理解:
爬取淘宝的商品信息
我们爬取一个淘宝的页面,其实静态很难爬取,淘宝的反爬虫措施相当到位,我们可以先用最简单的方式尝试一下:
importbs4importrequests r = requests.get("https://s.taobao.com/search?q=surface&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.7724922.8452-taobao-item.1&ie=utf8&initiative_id=tbindexz_20160228")data = r.contentsoup = bs4.BeautifulSoup(data)fortaginsoup.tagStack:printtag.encode('gbk','ignore')
我们发现结果:
同时我们发现,通过这种方式获得的html中是没有商品信息的。这样基本所有的静态方式都不可以使用了。
但是selenium的办法是直接操作浏览器所以淘宝并不能挡得住这种数据搜集。
我们先简单看一下能否获取到这个淘宝页面:
from selenium import webdriverimporttimedriver = webdriver.PhantomJS(executable_path="phantomjs.exe")driver.get("https://s.taobao.com/search?q=surface&imgfile=&commend=all&ssid=s5-e&search_type=item&sourceId=tb.index&spm=a21bo.7724922.8452-taobao-item.1&ie=utf8&initiative_id=tbindexz_20160228")time.sleep(7)printdriver.page_source.encode('gbk','ignore')#这个函数获取页面的htmldriver.get_screenshot_as_file("2.jpg")#获取页面截图print"Success To Create the screenshot & gather html"driver.close()
我们还是轻松加愉快的拿到了商品信息,查看文件夹下的截图文件:
2.jpg就是我们截图的文件,打开发现图片显然是没有加载出来的,实际的效果应该是全部图片都加载出来:
放大即可看到高清的网页截图:
这个时候我们有了html可以进行静态解析数据挖掘了。
这里值得提一下的是,selenium注重对单个元素的操作,beautifulsoup注重对html页面的分析和数据分类处理,所以两者结合可以达到非常好的效果,但是大家在使用的过程中就会发现一个问题,使用selenium打开phantomjs的速度有点慢,当然大家还可以用firefox或者是chrome,这些都是selenium支持的。
Have Fun!
其实selenium还有各种各样神奇的功能,比如如果你要自动填写web应用的表单,selenium绝对比什么按键精灵好用的多的很。
0×05 匿名爬虫
有时候比较烦的是,我们使用爬虫来工作,某些情况下IP受限制,这造成了很大的麻烦,如果这个爬虫在服务器端的时候,也许还好,服务器可以提供多个可以选择的IP,但是作为一只家养的爬虫,IP被锁定以后,着实头疼。
当然所谓的匿名爬虫也就是一种以匿名方式请求目标页面,然后获取到页面结果。
0×06 匿名爬虫解决方案(from《webscraping with python》)
Tor+PySocks
Tor的使用https://www.torproject.org/
PySocks设置代理
非selenium的匿名浏览设定使用方法:
importsocksimportsocketfromurllib.requestimporturlopen#假设tor在9999号端口启动socks.set_default_proxy(socks.SOCKS5,'localhost',9999)socket.socket = socks.socksocketprinturlopen('target_web').read()
使用selenium的匿名方式:
fromseleniumimportwebdriver#假定9999端口开启tor服务service_args = ['--proxy=localhost:9999','--proxy-type=socks5', ]driver =webdriver.PhantomJS(executable_path="phantomjs.exe",service_args=service_args)driver.get("target_url")printdriver.page_sourcedriver.close()