Scrapy 是一个用来抓取数据的应用级框架。我们可以用它来抓取网站并提取结构化数据,这些数据通常是应用广泛的,例如用于数据挖掘,信息处理,以及存储历史档案等。
尽管 Scrapy 的最初设计是为了提取网页数据,它也可以用来提取API数据 (例如 Amazon Associates Web Services) 或者是作为一般意义的网页抓取。
这份文档的主要目的就是向你介绍Scrapy的主要概念,让你了解Scrapy是如何工作的,进而决定Scrapy是不是你想要的。
当你准备好开启一个工程的时候,你可以看这个位置 start with the tutorial。
那么,你需要从一个网站提取一些信息,但是这个网站并没有提供任何API或者是可编程的途径使用信息。 Scrapy可以帮助你提取这些信息。
假设我们想提取网站Mininova中所有今天添加文件的的URL, name, description 和size。
今天刚添加的文件列表可以在下面这个网页中获得:
http://www.mininova.org/today
如上图所示做好项目的准备工作,在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()
下面我们要写一个蜘蛛代码,其中定义了起始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> > <a href="/sub/35">Documentary</a></p><p><strong>Total size:</strong>150.62 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代码中定义的。
进行完上面的步骤,我们将运行这个蜘蛛来抓取网页,并把抓取的信息转换成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插件,只能抓下几个回车,所以这个问题留待将来进行解决。
如果你在蜘蛛成功运行后打开文件 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 )要做的了。
你已经知道了如何使用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 images (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
A 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
A 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