使用Scrapy递归爬取网页

1. scrapy介绍与安装

  Scrapy,Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。(百度百科的描述)
  
  安装过程见CentOS7下安装Scrapy,基于Python2.7.5版本。

2. 项目代码与分析

(1)创建项目

scrapy startproject FinancialSpider

  可使用scrapy -h 获取使用帮助。

  生成的项目目录结构如下:  

FinancialSpider/
    FinancialSpider/
        spiders/
            __init__.py
        __init__.py
        items.py
        pipelines.py
        settings.py
    scrapy.cfg

  
主要有几个部分:

  • items.py —— 用于从网页中提取结构化数据,spider会将数据以dict形式返回
  • pipelines.py —— 用于item数据的清洗,验证,查重,保存
  • settings.py —— 用于自定义所有scrapy组件的行为
  • spiders/ —— 在该目录下的文件中定义爬虫类,用于定义爬取和解析网页的方式

(2)定义Items

import scrapy

class FinancialspiderItem(scrapy.Item):
    # define the fields for your item here like:
    html_content = scrapy.Field()

(注:本项目基于scrapy1.2.0,不同版本代码可能有差异,后文不再叙述)

由于需要抓取整个网页内容,故定义一个Field对象。

(3)定义Pipelines

import codecs

class FinancialspiderPipeline(object):
    def __init__(self):
        self.file = codecs.open('financial_file1', mode='ab', encoding='utf-8')

    def process_item(self, item, spider):
        content = item['html_content']
        #self.file.write(content.decode("unicode_escape"))
        self.file.write(content)
        return item

  初始化时以追加的模式打开数据将要保存的文件。
  
  每个Pipeline组件需要实现process_item方法,参数item为抓取的Item对象,spider为抓取item的Spider对象。方法可返回Item对象,或者raise DropItem Exception等。

  在此,将Item中的值写入保存文件。

(4)定义Settings

Settings提供了key-value映射的全局命名空间,代码中可以获取配置的值。settings.py是scrapy项目的标准配置文件,也可通过命令行选项,spider类中等方式定义。

ROBOTSTXT_OBEY = False

是否遵循robots.txt协议

COOKIES_ENABLED = False

防止了网站使用cookies识别爬虫

ITEM_PIPELINES = {
   'FinancialSpider.pipelines.FinancialspiderPipeline': 300,
}

激活自定义的Pipeline组件

DOWNLOAD_TIMEOUT = 15

减少下载超时时间,以便越过太慢的连接请求,快速进行下一网页的抓取

DUPEFILTER_CLASS = 'scrapy.dupefilters.RFPDupeFilter'

默认的重复请求检测过滤,可自己实现RFPDupeFilter的子类,覆写其request_fingerprint方法。

DEPTH_PRIORITY = 1
SCHEDULER_DISK_QUEUE = 'scrapy.squeues.PickleFifoDiskQueue'
SCHEDULER_MEMORY_QUEUE = 'scrapy.squeues.FifoMemoryQueue'

scrapy默认使用LIFO队列存储请求,即以深度优先方式进行抓取。通过以上设置,以广度优先方式进行抓取。

(5)定义Spider

from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from scrapy.selector import Selector

from FinancialSpider.items import FinancialspiderItem

class FinancialSpider(CrawlSpider):
    """继承自CrawlSpider,实现自动爬取的爬虫。"""

    name = 'FinancialSpider'

    download_delay = 1
    # make scrapy crawl any site without allowed domains restriction
    #allowed_domains = ['eastmoney.com']
    start_urls = ['http://www.eastmoney.com']


    rules = [
        Rule(LinkExtractor(allow=(),
             restrict_xpaths=('//a[@href]')),
             callback='parse_item',
             follow=True)
    ]

    def parse_start_url(self, response):
        item = FinancialspiderItem()
        sel = Selector(response)

        content_list = sel.xpath('/html').extract()

        content = content_list[0]

        item['html_content'] = content + u'\n'

        return item


    def parse_item(self, response):
        item = FinancialspiderItem()
        sel = Selector(response)

        content_list = sel.xpath('/html').extract()

        if len(content_list) > 0:
            content = content_list[0]

            # print type(content_list)
            # print "content_len: "
            # print len(content_list)

            #print type(content)

            #item['html_content'] = [n.encode('utf-8') for n in content]
            item['html_content'] = content + u'\n'

        yield item

  在此设置了download_delay为1秒,以免访问频繁被服务器禁止访问,经验证,已满足需求。

  CrawlSpider是Spider的子类,提供了通过定义一系列rule来跟踪链接的更便利的机制。由于需要递归爬取网页,CrawlSpider更加方便。

  Rule对象定义了爬取网站的特定行为。其第一个参数Link Extractor object描述了从每个爬取网页中提取链接的方式,callback参数用于处理Link Extractor 提取的链接。

  parse_start_url方法为CrawlSpider特有的方法,用于处理start_urls指定页面的response。
  在parse_item方法中使用Selector并通过XPath实现数据的提取,在此提取的是html标签中的所有内容。

(6)使用user agent池

使用user agent池,避免服务器禁止访问。具体代码和说明参见 Scrapy研究探索(七)——如何防止被ban之策略大集合

(7)启动爬虫程序

在shell中,进入第一个FinancialSpider目录,使用以下命令启动爬虫

scrapy crawl FinancialSpider --logfile=log --loglevel=WARNING

可以看到,保存文件生成在下级目录下,内容不断增大。

(8)停止爬虫程序

可在Shell中通过按下两次ctrl-c停止爬虫。
若爬虫在后台运行,可执行两次下列代码,实现同样功能。

kill -2 $(ps -ef | grep FinancialSpider | awk '{print $2}')

3. 后续研究工作

  • 通过scrapy-redis实现分布式爬取
  • JS爬取
  • scrapy源码研究
  • ……

4. 参考文章

  1. Scrapy 1.2 documentation https://doc.scrapy.org/en/1.2/
  2. Scrapy系列教程 by young-hz http://blog.csdn.net/u012150179/article/category/2345511

猜你喜欢

转载自blog.csdn.net/lujian1989/article/details/53046576