超级易懂爬虫系列之使用scrapy爬取动态网页

栏目: Python · 发布时间: 7年前

内容简介:超级易懂爬虫系列之使用scrapy爬取动态网页

在前面通过超级易懂爬虫系列的讲解,相信大家对爬虫已经很熟悉了,还没看的同学可以先去了解一下

但是不知道大家发现没前面一系列的爬取的网页都是静态的html网页,所谓静态网页就是当浏览器加载完该页面后,页面的展示效果就是固定的了,因为代码不能更改了,但是很显然某些网页不是这样的,如一些论坛网站,购物网站,网友可能会上传自己的买家秀,或者对买的东西做个评价,很显然这是随机的,因此不同的时候加载该页面其内容是不一样的,因为可能增加了新的内容,这就是动态网站,动态网站可能会随不同客户、不同时间,返回不同的页面。静态网页一般而言都是以htm,html,xml结尾的,而动态网页一般以php,asp结尾。关于动态网站和静态网站的更多差异可以看: 如何来区分静态网页与动态网页 而动态网页的很多节点信息内容在html文件中是不存在的,当用户与网页交互之后才会显示出来,这样就给我们前面写的爬虫的例子带来了一个麻烦,因为前面的爬虫都是爬取的静态网页,我们要获取的节点信息都是在html文件中的,但是动态网页的某些节点信息是通过用户交互点击之后才可以显示出来的,因此爬虫获取不到这些信息。那么要怎样让爬虫获取到这些信息呢?其实也很简单,虽然前面的爬虫爬取不到隐藏的信息,但是我们通过浏览器浏览这些网页的时候是可以看到这些信息的,因为浏览器已经帮我们完成了动态网页的加载过程,那么我们是不是可以模拟浏览器请求,让其加载完动态网页,此时所有的节点信息都包含在了已经加载完成的网页中,此时我们就可以像爬取静态网页那样爬取我们感兴趣的数据了。那么我们要怎样模拟浏览器的访问行为呢?这就需要用到selenium。selenium 是一个web的自动化测试工具,支持多种主流浏览器,Selenium测试直接运行在浏览器中,就像真正的用户在浏览器中打开某个网页一样。我们首先来看一下不使用selenium直接爬取动态网页的情况,然后在来看下使用selenium访问的情况。

首先选一个具备动态网页的页面,这里我选择的是百度贴吧杨紫吧我家女神最新电视剧_龙珠传奇的美图为例, http://tieba.baidu.com/p/4721853678#!/l/p1 ,我们的目标是将该页面的美图全部爬取下来,还是按照原来和大家讲的方式按F12,然后找到我们需要获取的图片的下载地址,如图以我家女神最帅气的那一张图片为例,可以看到下载地址位于<a  class =” ag_ele_a “标签下,如图所示,

超级易懂爬虫系列之使用scrapy爬取动态网页

好了知道了我们感兴趣的数据之后就可以开始抓取数据了,打开我们上次使用scrapy爬取妹纸图的程序,然后将start_urls修改为上述地址,然后在parse函数中先把解析后的网页源代码打印出来看下,此时程序如下:

#定义spider组件,继承自scrapy.Spider
class Spider(scrapy.Spider):
 
 
    name = "spider_girl"
    allowed_domains = ["tieba.baidu.com"]
    start_urls = ["http://tieba.baidu.com/p/4721853678#!/l/p1"] #指定需要爬取的起始url
 
    # 用来去重的集合,首先将起始网址添加进去
    crawed_urls = {"http://tieba.baidu.com/p/4721853678#!/l/p1"}
 
    #设置自己的cookies
    cookies = {}
    #设置自己的headers
    headers = {
         'Connection': 'keep - alive',
        'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36'
    }
 
 
    #重写该函数,在该函数中返回Request对象,可以设置cookies,headers参数
    def start_requests(self):
        yield Request(self.start_urls[0],callback=self.parse, headers=self.headers)
 
     #只需要重写该函数即可,框架会自动回调该函数
    def parse(self, response):
        print response.text

然后可以看到控制台输出了该页面的源代码,然后我们先在该输出内容中查找一下 class =” ag_ele_a “试试,结果却显示在该页面的输出代码中没查找到 class =” ag_ele_a “,如图:

超级易懂爬虫系列之使用scrapy爬取动态网页

纳尼?怎么会查找不到呢?在前面浏览器打开的网页的代码中明明是可以看到 class =” ag_ele_a “,也正是如此,我们才确定了查找标签为为<a  class =” ag_ele_a “>,现在怎么会不存在呢?这是因为该网页是动态网页,我们看到的结果是经过浏览器渲染加载完成之后的结果,但是直接使用scrapy爬取的网页是静态网页的内容,因此是不包含那些通过script脚本等方式动态加载的内容的,这也是为何在前面说到爬取动态网页需要使用selenium的原因。下面我们先来了解一下selenium,然后使用selenium改写上述代码,看能否爬取到动态生成的内容class=”ag_ele_a”。

selenium的安装与使用

selenium的安装可以使用pip命令安装,windows下打开cmd,输入如下命令即可:

pip install selenium

或者在pycharm中导入下面的语句:

from selenium import webdriver

然后IDE会自动在selenium下显示红色波浪线,表示该库还未安装,我们只需要将鼠标定位到selenium,然后使用快捷键alt+enter会自动弹出安装该库的选项,然后点击该选项IDE会自动帮我们安装,推荐使用该方式安装。

安装完成之后就可以使用该模块了,主要是使用selenium的webdriver模块,首先构造一个webdriver对象,然后使用该对象的get()函数,即可模拟一个网络请求,如果要查看请求之后的网页的代码,可以使用该对象的page_source属性。即代码如下:

#构造一个webdriver对象
browser = webdriver.Ie(executable_path='D:\IEDriver\IEDriverServer.exe')
#模拟网络请求
browser.get(self.start_urls[0])
#输出请求后的网页页面源代码
print browser.page_source

上述代码中构造webdriver对象此处使用的是IE浏览器,需要传入的参数是对应的浏览器的driver程序的路径。因此使用webdriver之前需要下载对应的浏览器的驱动程序,这是官网下载地址: https://sites.google.com/a/chromium.org/chromedriver/downloads 下载完成之后需要将该路径添加到系统环境变量的path中,否则运行时会出现WebDriverException: Message: ‘IEDriverServer.exe’ executable needs to be in PATH的错误,如图:

超级易懂爬虫系列之使用scrapy爬取动态网页

然后就可以使用webdriver模块了,代码如下:

#定义spider组件,继承自scrapy.Spider
class Spider(scrapy.Spider):
 
    name = "spider_girl"
    allowed_domains = ["tieba.baidu.com"]
    start_urls = ["http://tieba.baidu.com/p/4721853678#!/l/p1"] #指定需要爬取的起始url
 
    # 用来去重的集合,首先将起始网址添加进去
    crawed_urls = {"http://tieba.baidu.com/p/4721853678#!/l/p1"}
 
    #设置自己的cookies
    cookies = {}
    #设置自己的headers
    headers = {
         'Connection': 'keep - alive',
        'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36'
    }
 
    #构造一个webdriver对象
    def __init__(self):
        self.browser = webdriver.Ie(executable_path='D:\IEDriver\IEDriverServer.exe')
 
    #释放webdriver对象
    def __del__(self):
        self.browser.close()
 
    #重写该函数,在该函数中返回Request对象,可以设置cookies,headers参数
    def start_requests(self):
        self.browser.get(self.start_urls[0])
        yield Request(self.start_urls[0],callback=self.parse, headers=self.headers)
 
     #只需要重写该函数即可,框架会自动回调该函数
    def parse(self, response):
        print self.browser.page_source

然后运行该程序,打印出此时的网页的源代码,然后搜索class=”ag_ele_a”字符串,可以发现可以搜索到,也就是说该动态网页的内容已经可以爬取到了,如图:

超级易懂爬虫系列之使用scrapy爬取动态网页

另外可以看到,当我们运行程序的时候会自动打开一个IE浏览器实例,而且即使网页url相同,多次运行会打开多个浏览器实例。这也是为何能够抓取到动态网页的原因,selenium的webdriver模拟了用户使用浏览器打开该网页的行为,因此获取到的网页是经过浏览器加载渲染完成的网页,也就是说抓取到的内容和我们前面使用F12在Elements选项卡中看到的代码一样。但是另外前面说过使用该方式会打开IE浏览器,显然这样不太好,一方面会冒出一个浏览器页面出来,另一方面打开的浏览器会占用系统资源,降低程序运行效率,那么能不能不打开浏览器产生同样的效果呢?答案就是使用PhantomJS。

关于selenium的更多的API大家可以去看官方文档,这里是官方文档地址: http://selenium-python.readthedocs.io/api.html

PhantomJS

PhantomJS是一个无界面的,可脚本编程的WebKit浏览器引擎.与上面提到的selenium一样可以用来模拟浏览器的行为,不过PhantomJS是无界面的,因此不会出现前面提到的打开一个浏览器窗口的行为,使用PhantomJS与使用webdriver一样需要先安装该软件,这里是官网下载地址: http://phantomjs.org/download.html 下载安装之后也需要将其添加到系统环境变量中,然后就可以使用webdriver调用该模块。

self.browser = webdriver.PhantomJS(executable_path=r'D:\spider_tool\phantomjs-2.1.1-windows\bin\phantomjs.exe')

如果运行时出现WebDriverException: Message: ‘phantomjs.exe’ executable needs to be in PATH,但是事实上phantomjs.exe已经添加到了系统环境变量中的话,则需要在传入的字符串参数的前面加上r,即

executable_path=r'D:\spider_tool\phantomjs-2.1.1-windows\bin\phantomjs.exe'

这样就不会出现那个错误了,这样就可以实现模拟浏览器访问网页同时不用打开浏览器的效果,如果大家想了解关于phantomjs的更多知识,可以参考官方文档: http://phantomjs.org/quick-start.html

讲解完了基本理论之后,接下来就开始使用webdriver和phantomjs来改写上次的程序吧。

#定义spider组件,继承自scrapy.Spider
class Spider(scrapy.Spider):
 
    name = "spider_girl"
    allowed_domains = ["tieba.baidu.com"]
    start_urls = ["http://tieba.baidu.com/p/4721853678#!/l/p1"] #指定需要爬取的起始url
 
    # 用来去重的集合,首先将起始网址添加进去
    crawed_urls = {"http://tieba.baidu.com/p/4721853678#!/l/p1"}
 
    #设置自己的cookies
    cookies = {}
    #设置自己的headers
    headers = {
         'Connection': 'keep - alive',
        'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.82 Safari/537.36'
    }
 
    #构造一个webdriver对象
    def __init__(self):
        self.browser = webdriver.PhantomJS(executable_path=r'D:\spider_tool\phantomjs-2.1.1-windows\bin\phantomjs.exe')
        #self.browser = webdriver.Ie(executable_path='D:\IEDriver\IEDriverServer.exe')
 
    #释放webdriver对象
    def __del__(self):
        self.browser.close()
 
    #重写该函数,在该函数中返回Request对象,可以设置cookies,headers参数
    def start_requests(self):
        self.browser.get(self.start_urls[0])
        yield Request(self.start_urls[0],callback=self.parse, headers=self.headers)
 
     #只需要重写该函数即可,框架会自动回调该函数
    def parse(self, response):
        
        soup = BeautifulSoup(self.browser.page_source, 'html.parser', from_encoding='utf-8')
        all_a=soup.find_all('a', class_='ag_ele_a')
 
        for a in all_a:
            src = a.find('img')['src']
            #print 'src is',src
 
            item=ImageItem()  #实例化item对象,该对象是我们在items.py中定义的
            item['img_src']=src
            yield item

只需要改写spider模块即可,主要就是通过webdriver.PhantomJS先构造一个webdriver对象,然后使用

self.browser.get(self.start_urls[0])

来模拟浏览器访问动态网页的行为,然后需要注意的是此时self.browser.page_source才是解析后的动态网页的代码而不是parse函数的response参数,即需要将self.browser.page_source传给BeautifulSoup作为第一个参数。

运行上述程序,可以看到控制台输出了妹纸图的下载地址,在磁盘的C:\Users\htq\Desktop\girl_目录下已经自动为我们下载好了女神的美图哦,

超级易懂爬虫系列之使用scrapy爬取动态网页

是不是很简单,是不是很激动,哈哈!恭喜大家已经学会了爬取动态网页的内容哦,赶快去贴吧爬取你家爱豆的美图吧!

注:本文首次发表于www.huqi.tk,谢绝转载,如需转载,请注明出处:www.huqi.tk


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

爆品战略

爆品战略

金错刀 / 北京联合出版公司 / 2016-7-1 / 56.00

◆ 划时代的商业著作!传统企业转型、互联网创业的实战指南! ◆ 爆品是一种极端的意志力,是一种信仰,是整个企业运转的灵魂! ◆ 小米创始人雷军亲自作序推荐!小米联合创始人黎万强、分众传媒创始人江南春、美的董事长方洪波、九阳董事长王旭宁等众多一线品牌创始人联袂推荐! ◆ 创图书类众筹新纪录!众筹上线2小时,金额达到10万元;上线1星期,金额突破100万元! ◆ 未售......一起来看看 《爆品战略》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

随机密码生成器
随机密码生成器

多种字符组合密码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具