用Scrapy框架做网页爬虫

前言

一直以来都非常想做一个网页爬虫,用来自动收集归档网页端的数据和一些有用的信息。前面尝试过自己完全用python实现,但是由于对这些东西并不熟悉,所以写得太差,毫无实用性可言。这也是工作中一直使用C++遗留下来的坏习惯——什么东西都想自己写,虽然早就明白“不要重复制造轮子”。

于是前几天就开始寻找开源的网页爬虫框架,网上有人统计排名前50的开源爬虫框架http://www.open-open.com/lib/view/open1422112155796.html,于是我就选择了排名比较靠前且与python更相近的Scrapy。

Scrapy的介绍

由于我自己是刚刚接触Scrapy,它的一些特性我是完全不知道,所以在这里我只能是引用百科里的介绍了(不用说明出处了,因为各大中文百科介绍都一个样):

Scrapy,Python开发的一个快速,高层次的屏幕抓取和web抓取框架,用于抓取web站点
并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化
测试。 Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改。
它也提供了多种类型爬虫的基类,如BaseSpider、sitemap爬虫等,最新版本又提供了
web2.0爬虫的支持。


Scrapy的安装

由于Scrapy是用python开发的,所以安装Scrapy前python的环境需要安装好是必须的。具体安装说明参考官方的文档的Installation guide部分。

由于我的机器有安装pip工具,所以我直接用pip安装:

pip install Scrapy


Scrapy的初步使用

  1. 创建Scrapy工程目录

    在命令行界面下输入如下命令(创建根目录名为tutorial):

    scrapy startproject tutorial
    
    
    

    生成目录结构如下:

    tutorial/
        scrapy.cfg            # deploy configuration file
        tutorial/             # project's Python module, you'll import your code from here
            __init__.py
            items.py          # project items file
            pipelines.py      # project pipelines file
            settings.py       # project settings file
            spiders/          # a directory where you'll later put your spiders
                __init__.py
                ...
    
    
  2. 编写spider类

    在tutorial/spiders目录中创建myspider.py(文件名随意)

    引用官方文档的参考代码,地址:http://doc.scrapy.org/en/latest/intro/tutorial.html(由于dmoz网站的代码有更新,所以例子中的代码现在是获取不了需要的数据的):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    import scrapy

    from tutorial.items import DmozItem

    class DmozSpider(scrapy.Spider):
    name = "dmoz"
    allowed_domains = ["dmoz.org"]
    start_urls = [
    "http://www.dmoz.org/Computers/Programming/Languages/Python/",
    ]

    def parse(self, response):
    for href in response.css("ul.directory.dir-col > li > a::attr('href')"):
    url = response.urljoin(href.extract())
    yield scrapy.Request(url, callback=self.parse_dir_contents)

    def parse_dir_contents(self, response):
    for sel in response.xpath('//ul/li'):
    item = DmozItem()
    item['title'] = sel.xpath('a/text()').extract()
    item['link'] = sel.xpath('a/@href').extract()
    item['desc'] = sel.xpath('text()').extract()
    yield item

    修改item.py中的代码:

    1
    2
    3
    4
    5
    6
    import scrapy

    class DmozItem(scrapy.Item):
    title = scrapy.Field()
    link = scrapy.Field()
    desc = scrapy.Field()

    DmozSpider类需要继承于scrapy.Spider类,名字随意定。DmozSpider中name需要唯一,表示爬虫的名字。start_urls是起始网页列表,爬虫从这些网页开始爬行。

    爬虫开始后会为start_urls列表中每一条url创建一个scrapy.Request对象,而它将parse函数作为其回调函数。在这个列子中parse函数的作用是解析页面中的需要爬的url。而parse_dir_contents函数的作用是解析出页面的数据。

    解析的数据用DmozItem记录。

  3. 启动爬虫

    以上面的例子,使用如下命令启动爬虫,”dmoz”便是前面DmozSpider类中定义的name:

    scrapy crawl dmoz
    
    
    

    将数据输出在json文件中:

    scrapy crawl dmoz -o items.json
    
    
    

XPath的使用

要获取页面中的数据,必然需要定位HTML文档中的节点。Scrapy将自己的机制称之为selectors,通过 XPath 和 CSS expression的两种方法定位。

由于XPath是使用得更为广泛,所以我主要使用XPath表达式来地位网页中的元素节点。在w3c的网站上有详细的XPath的教程:http://www.w3school.com.cn/xpath/index.asp

我这里说明一些注意点:

  1. 只有用”//“定位时才可以省略其前面的先辈节点,其他的需要一层一层的定位。
  2. “@”符号用于指定节点的属性,用法如:’//div[@id=”not-exists”]/text()’
Compartir