Scrapy at a glance

Scrapy小介

Scrapy 是一个用来抓取数据的应用级框架。我们可以用它来抓取网站并提取结构化数据,这些数据通常是应用广泛的,例如用于数据挖掘,信息处理,以及存储历史档案等。

尽管 Scrapy 的最初设计是为了提取网页数据,它也可以用来提取API数据  (例如 Amazon Associates Web Services) 或者是作为一般意义的网页抓取。

这份文档的主要目的就是向你介绍Scrapy的主要概念,让你了解Scrapy是如何工作的,进而决定Scrapy是不是你想要的。

当你准备好开启一个工程的时候,你可以看这个位置 start with the tutorial

Pick a website

选取一个页面

那么,你需要从一个网站提取一些信息,但是这个网站并没有提供任何API或者是可编程的途径使用信息。 Scrapy可以帮助你提取这些信息。

假设我们想提取网站Mininova中所有今天添加文件的的URL, name, description 和size。

今天刚添加的文件列表可以在下面这个网页中获得:

http://www.mininova.org/today

Define the data you want to scrape

定义想要抓取的数据

spacer.gifwKiom1ODDVnSvJtrAAE_XCuV_gA832.jpg

如上图所示做好项目的准备工作,在cmd中输入scrapy startproject testOfscrapy 用来创建一个scrapy工程,它的名字是testOfscrapy。

这之后会发现在Python27/projects目录下多了一个路径testOfscrapy 。在里面找到item文件,进行修改。

第一步就是要先定义我们所要抓取的信息。在 Scrapy中,这个环节要从这个 Scrapy Items(本例中指的是files)中定义。

我的Item文件应该像下面这样:

from scrapy.item import Item, Fieldclass TestofscrapyItem(Item):
	url = Field()
	name = Field()
	description = Field()
	size = Field()

Write a Spider to extract the data

写个用来抽取数据的蜘蛛代码

下面我们要写一个蜘蛛代码,其中定义了起始URL (http://www.mininova.org/today), 后续链接的规则,提取数据的规则等。

仔细看一下网页的内容,不难发现所有文件的 URLs都具备这样的规律http://www.mininova.org/tor/NUMBER (NUMBER的位置是一串整数)。借助这一点,我们为链接地址构建一套规律的表达式,如下所示: /tor/\d+.

我们将使用 XPath 从网页的HTML源文件中选择要提取的数据。下面我们来看一个例子页面:

http://www.mininova.org/tor/2676093

根据这个页面的 HTML 源码来构建XPath,从而选取我们想要的部分:文件名,描述信息以及大小。

从这个页面的 HTML 源码中,我们能够看出文件名包含在一个 <h1> 标签中:

<h1>Darwin - The Evolution Of An Exhibition</h1>

提取文件名的XPath表达式可以写成如下的样子:

//h1/text()

描述信息包含在一个 <div> 标签中,它带有一个属性 id="description":

<h2>Description:</h2><div id="description">Short documentary made for Plymouth City Museum and Art Gallery regarding the setup of an exhibit about Charles Darwin in conjunction with the 200th anniversary of his birth.

...

提取描述信息的XPath表达式可以写成如下的样子:

//div[@id='description']

最后一项,文件大小信息包含在第二个 <p> 标签中, 这个标签又在 一个带有属性id=specifications的<div> 标签中:

<div id="specifications"><p><strong>Category:</strong><a href="/cat/4">Movies</a> &gt; <a href="/sub/35">Documentary</a></p><p><strong>Total size:</strong>150.62&nbsp;megabyte</p>

提取文件大小的XPath表达式可以写成如下的样子:

//div[@id='specifications']/p[2]/text()[2]

想要学习XPath的更多内容请参看 XPath reference.

整个蜘蛛的代码如下:

from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import Selector
from testOfscrapy.items import TestofscrapyItem
class MininovaSpider(CrawlSpider):
    name = 'mininova'
    allowed_domains = ['mininova.org']
    start_urls = ['    rules = [Rule(SgmlLinkExtractor(allow=['/tor/\d+']), 'parse_torrent')]
    def parse_torrent(self, response):
        sel = Selector(response)
        torrent = TestofscrapyItem()
        torrent['url'] = response.url
        torrent['name'] = sel.xpath("//h1/text()").extract()
        torrent['description'] = sel.xpath("//*[@id='description']/text()[1]").extract()            
        torrent['size'] = sel.xpath("//div[@id='specifications']/p[2]/text()[2]").extract()
        return torrent

TestofscrapyItem 就是在上面item代码中定义的。

Run the spider to extract the data

运行蜘蛛提取数据

进行完上面的步骤,我们将运行这个蜘蛛来抓取网页,并把抓取的信息转换成JSON格式保存在一个输出文件 scraped_data.json 中:

scrapy crawl mininova -o scraped_data.json -t json(注意要先进入)testOfscrapy目录再运行这个命令

这个命令使用流式输出( feed exports生成JSON文件。你可以轻松的修改输出的格式 (例如 XML 或者 CSV) 和后端存储 (例如FTP 或者 Amazon S3).

你也可以写一个 item pipeline 来把内容存储到数据库中。

注意:在这个步骤中,我遇到了一点问题,网页的格式可能发生了变化,原来的XPath进行了小小的修改,能够成功的进行抓取了。但是description这一项却迟迟没有抓下来,

考虑网站管理者可能更新了网站,使用了js插件,只能抓下几个回车,所以这个问题留待将来进行解决。

Review scraped data

检阅获取的数据

如果你在蜘蛛成功运行后打开文件 scraped_data.json, 你会看到像下面这样抓取到的内容:

[{"url": "http://www.mininova.org/tor/2676093", "name": ["Darwin - The Evolution Of An Exhibition"], "description": ["Short documentary made for Plymouth ..."], "size": ["150.62 megabyte"]},# ... other items ...]

你会发现所有的抓取条目都被陈列出来, (除了 url 是直接被分配的以外) . 这是因为选择器( selectors )返回了列表。可能你只想存储一个值, 或者想执行一些附加的值操作。那就是项目加载器( Item Loaders )要做的了。

What else?

还有什么呢?

你已经知道了如何使用Scrapy去抓取并保存一些项目,但是这都是点皮毛。Scrapy提供了更多的强有力的支持来使得抓取更简单有效,例如下面这些:(下面就是介绍一些好处巴拉巴拉,不想翻译了,后面的部分还会慢慢翻译完的,都会讲到)

  • Built-in support for selecting and extracting data from HTML and XML sources

  • Built-in support for cleaning and sanitizing the scraped data using a collection of reusable filters (called Item Loaders) shared between all the spiders.

  • Built-in support for generating feed exports in multiple formats (JSON, CSV, XML) and storing them in multiple backends (FTP, S3, local filesystem)

  • A media pipeline for automatically downloading p_w_picpaths (or any other media) associated with the scraped items

  • Support for extending Scrapy by plugging your own functionality using signals and a well-defined API (middlewares, extensions, and pipelines).

  • Wide range of built-in middlewares and extensions for:

    • cookies 和会话控制

    • HTTP 压缩

    • HTTP 认证

    • HTTP 缓存

    • 代理用户欺骗

    • robots.txt

    • 抓取深度限制

    • 更多

  • Robust encoding support and auto-detection, for dealing with foreign, non-standard and broken encoding declarations.

  • Support for creating spiders based on pre-defined templates, to speed up spider creation and make their code more consistent on large projects. See genspider command for more details.

  • Extensible stats collection for multiple spider metrics, useful for monitoring the performance of your spiders and detecting when they get broken

  • An Interactive shell console for trying XPaths, very useful for writing and debugging your spiders

  • System service designed to ease the deployment and run of your spiders in production.

  • A built-in Web service for monitoring and controlling your bot

  • Telnet console for hooking into a Python console running inside your Scrapy process, to introspect and debug your crawler

  • Logging facility that you can hook on to for catching errors during the scraping process.

  • Support for crawling based on URLs discovered through Sitemaps

  • A caching DNS resolver