Python爬虫开发(四):动态加载页面的解决方案与爬虫代理

2016-03-01 1092244人围观 ,发现 28 个不明物体 WEB安全头条

*原创作者:VillanCh

文章合集:

Python爬虫开发(一):零基础入门 Python爬虫开发(二):整站爬虫与Web挖掘
Python爬虫开发(三):数据存储以及多线程
Python爬虫开发(三-续):快速线程池爬虫
Python爬虫开发(四):动态加载页面的解决方案与爬虫代理 Python爬虫开发(五):反爬虫措施以及爬虫编写注意事项

0×00 前言

0×01 动态页面解决方案Selenium+PhantomJS

0×02 原理回顾对比

0×03 Quick Start

0×04 webdriver API

0×05 匿名爬虫

0×06 匿名爬虫解决方案

0×07 完结总结

0×00 前言

如果读者读过我前面的关于爬虫的文章,应该大概都清楚我们现在可以对一个静态的web页面”为所欲为“了,但是技术的发展总是没有止境的,仅仅是这样对静态页面处理远远不够,要知道现在很多的web页面有意无意为了防止静态爬虫使用ajax技术动态加载页面,这就导致了在面对这些网站的时候,我们前面的技术并不能起到什么很好的效果,所以,我在本系列文章开头就说了会提供动态加载网页的解决方案,在这篇文章里,笔者就在这里提出这个解决方案,用来解决以前我们没有办法的问题。

0×01 动态页面解决方案Selenium+PhantomJS

Python2(或Python3)      本文使用Python2.7.11

Selenium                            自动化web测试解决方案

PhantomJS                         一个没有图形界面的浏览器

0×02 原理回顾对比

A1.png

讨论:讲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的情况:页面如下:

<html>
<head>
<title>Some JavaScript-loaded content</title>
<script src="../js/jquery-2.1.1.min.js"></script>
 
</head>
<body>
<div id="content">
This is some content that will appear on the page while it's loading. You don't care about scraping this.
</div>
 
<script>
$.ajax({
    type: "GET",
    url: "loadedContent.php",
    success: function(response){
 
        setTimeout(function() {
            $('#content').html(response);
        }, 2000);
    }
  });
 
function ajax_delay(str){
 setTimeout("str",2000);
}
</script>
</body>
</html>

我们简单看到这个web页面是使用ajax动态加载数据,GET请求LoadedContent.php然后把结果直接显示在content里。对于这样的方式我们并不需要太深入了解,总之我们只需要知道我们如果使用传统的方式获取,得到的就是上面的静态html而没有loadedContent.php中的内容。

作为selenium的爬虫应用quickstart,我们没必要太深入讲解原理,我们需要把PhantomJS和python脚本放在同一个文件夹下,建立selenium_test.py文件夹

A2.png

然后输入selenium_test.py中的内容:

#引入selenium中的webdriver
from selenium import webdriver
import time
#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获取元素的文本数据
print driver.find_element_by_id('content').text
 
#关闭浏览器
driver.close()

建议大家先用传统的方法尝试一下这个页面,再使用上面的脚本来执行。观察两个结果有什么不同。当然,我这里明确说明:如果大家真的不想再学习selenium的定位元素,发送数据等操作了,其实也是没什么问题的。通过一个叫page_source的属性,我们完全可以获取当前整个页面的和html,然后再把页面传给BeautifulSoup,这样我们仍然可以使用BeautifulSoup进行解析。 

0×04 Webdriver API

我们发现要使用selenium分析页面,导入的是webdriver,webdriver有很多易用的API:

定位元素,控制浏览器行为,刷新,web元素操作,模拟键盘鼠标事件,获得验证信息,设置等待时间,上传下载文件,调用javascript,窗口截图。

我们写简单的爬虫可能要用得到的就是元素定位和设置等待时间,笔者在这里利用这两个特性再写一个例子供大家理解:

A3.png

爬取淘宝的商品信息

我们爬取一个淘宝的页面,其实静态很难爬取,淘宝的反爬虫措施相当到位,我们可以先用最简单的方式尝试一下:

import bs4
import requests
 
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.content
soup = bs4.BeautifulSoup(data)
for tag in soup.tagStack:
print tag.encode('gbk','ignore')

我们发现结果:

A4.png

同时我们发现,通过这种方式获得的html中是没有商品信息的。这样基本所有的静态方式都不可以使用了。

但是selenium的办法是直接操作浏览器所以淘宝并不能挡得住这种数据搜集。

我们先简单看一下能否获取到这个淘宝页面:

from selenium import webdriver
import time
 
driver = 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)
print driver.page_source.encode('gbk','ignore') #这个函数获取页面的html
driver.get_screenshot_as_file("2.jpg") #获取页面截图
print "Success To Create the screenshot & gather html"
 
driver.close()

A5.png

我们还是轻松加愉快的拿到了商品信息,查看文件夹下的截图文件:

A6.png

2.jpg就是我们截图的文件,打开发现图片显然是没有加载出来的,实际的效果应该是全部图片都加载出来:

A7.png

放大即可看到高清的网页截图:

A8.png

这个时候我们有了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的匿名浏览设定使用方法:

import socks
import socket
from urllib.request import urlopen
#假设tor在9999号端口启动
socks.set_default_proxy(socks.SOCKS5, 'localhost', 9999)
socket.socket = socks.socksocket
print urlopen('target_web').read()

使用selenium的匿名方式:

from selenium import webdriver
#假定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")
print driver.page_source
driver.close()

0×07 完结总结

本系列文章大概用了4篇(附:Python高级爬虫:(一)(二)(三))共上万字的篇幅和很多个有趣的例子来揭示了爬虫的各项技术,旨在向广大爱好者解释爬虫技术,也为需要用到爬虫的开发者提供了一些切实可行的解决方案,如果大家喜欢本系列文章,可以在评论区留下您的意见。

如果问我有什么关于爬虫和web数据挖掘的入门书籍可以看,推荐《web scraping with python》和selenium之类的书籍可以供大家参考,这些书籍仅仅是入门,如果真的要设计一款商业的爬虫,每一个细节都要谨慎处理,算法,效率都是要考虑的问题。

*原创作者:VillanCh,本文属FreeBuf原创奖励计划文章,未经作者本人及FreeBuf许可,切勿私自转载

这些评论亮了

  • hehe 回复
    @ 我是只会做题的大牛
    还开什么车呀,你可以去人家php培训班大闹一番,
    老夫不想学习钱是怎么挣的,你给老夫钱就行。老夫绝对能比你们这些php程序员更利用到极致
    )9( 亮了
  • difcareer (3级) 我在简书上发起了一个Android安全专题,分为很多个子专题... 回复
    整个github呀, 避免重复造车
    )6( 亮了
发表评论

已有 28 条评论

取消
Loading...

特别推荐

推荐关注

填写个人信息

姓名
电话
邮箱
公司
行业
职位
css.php