看这篇文章的人,我假设大家都已经学会了python(派森),而后下面的知识都是python的扩展(框架)。html
在这篇入门教程中,咱们假定你已经安装了Scrapy。若是你尚未安装,那么请参考安装指南。python
咱们将使用开放目录项目(dmoz)做为抓取的例子。git
这篇入门教程将引导你完成以下任务:程序员
Scrapy是由Python编写的。若是你是Python新手,你也许但愿从了解Python开始,以期最好的使用Scrapy。若是你对其它编程语言熟悉,想快速的学习Python,这里推荐 Dive Into Python。若是你对编程是新手,且想从Python开始学习编程,请看下面的对非程序员的Python资源列表。github
新建工程正则表达式
在抓取以前,你须要新建一个Scrapy工程。进入一个你想用来保存代码的目录,而后执行:shell
Microsoft Windows XP [Version 5.1.2600] (C) Copyright 1985-2001 Microsoft Corp. T:\>scrapy startproject tutorial T:\>
这个命令会在当前目录下建立一个新目录tutorial,它的结构以下:编程
T:\tutorial>tree /f Folder PATH listing Volume serial number is 0006EFCF C86A:7C52 T:. │ scrapy.cfg │ └─tutorial │ items.py │ pipelines.py │ settings.py │ __init__.py │ └─spiders __init__.py
这些文件主要是:json
定义Itemapi
Items是将要装载抓取的数据的容器,它工做方式像python里面的字典,但它提供更多的保护,好比对未定义的字段填充以防止拼写错误。
它经过建立一个scrapy.item.Item类来声明,定义它的属性为scrpy.item.Field对象,就像是一个对象关系映射(ORM).
咱们经过将须要的item模型化,来控制从dmoz.org得到的站点数据,好比咱们要得到站点的名字,url和网站描述,咱们定义这三种属性的域。要作到这点,咱们编辑在tutorial目录下的items.py文件,咱们的Item类将会是这样
from scrapy.item import Item, Field class DmozItem(Item): title = Field() link = Field() desc = Field()
刚开始看起来可能会有些困惑,可是定义这些item能让你用其余Scrapy组件的时候知道你的 items究竟是什么。
咱们的第一个爬虫(Spider)
Spider是用户编写的类,用于从一个域(或域组)中抓取信息。
他们定义了用于下载的URL的初步列表,如何跟踪连接,以及如何来解析这些网页的内容用于提取items。
要创建一个Spider,你必须为scrapy.spider.BaseSpider建立一个子类,并肯定三个主要的、强制的属性:
这个方法负责解析返回的数据、匹配抓取的数据(解析为item)并跟踪更多的URL。
这是咱们的第一只爬虫的代码,将其命名为dmoz_spider.py并保存在tutorial\spiders目录下。
from scrapy.spider import BaseSpider class DmozSpider(BaseSpider): name = "dmoz" allowed_domains = ["dmoz.org"] start_urls = [ "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/", "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/" ] def parse(self, response): filename = response.url.split("/")[-2] open(filename, 'wb').write(response.body)
爬爬爬
为了让咱们的爬虫工做,咱们返回项目主目录执行如下命令
T:\tutorial>scrapy crawl dmoz
crawl dmoz 命令从dmoz.org域启动爬虫。 你将会得到以下相似输出
T:\tutorial>scrapy crawl dmoz 2012-07-13 19:14:45+0800 [scrapy] INFO: Scrapy 0.14.4 started (bot: tutorial) 2012-07-13 19:14:45+0800 [scrapy] DEBUG: Enabled extensions: LogStats, TelnetConsole, CloseSpider, WebService, CoreStats, SpiderState 2012-07-13 19:14:45+0800 [scrapy] DEBUG: Enabled downloader middlewares: HttpAuthMiddleware, DownloadTimeoutMiddleware, UserAgentMiddleware, RetryMiddleware, DefaultHeadersMiddleware, RedirectMiddleware, CookiesMiddleware, HttpCompressionMiddleware, ChunkedTransferMiddleware, DownloaderStats 2012-07-13 19:14:45+0800 [scrapy] DEBUG: Enabled spider middlewares: HttpErrorMiddleware, OffsiteMiddleware, RefererMiddleware, UrlLengthMiddleware, DepthMiddleware 2012-07-13 19:14:45+0800 [scrapy] DEBUG: Enabled item pipelines: 2012-07-13 19:14:45+0800 [dmoz] INFO: Spider opened 2012-07-13 19:14:45+0800 [dmoz] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 2012-07-13 19:14:45+0800 [scrapy] DEBUG: Telnet console listening on 0.0.0.0:6023 2012-07-13 19:14:45+0800 [scrapy] DEBUG: Web service listening on 0.0.0.0:6080 2012-07-13 19:14:46+0800 [dmoz] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/> (referer: None) 2012-07-13 19:14:46+0800 [dmoz] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> (referer: None) 2012-07-13 19:14:46+0800 [dmoz] INFO: Closing spider (finished) 2012-07-13 19:14:46+0800 [dmoz] INFO: Dumping spider stats: {'downloader/request_bytes': 486, 'downloader/request_count': 2, 'downloader/request_method_count/GET': 2, 'downloader/response_bytes': 13063, 'downloader/response_count': 2, 'downloader/response_status_count/200': 2, 'finish_reason': 'finished', 'finish_time': datetime.datetime(2012, 7, 13, 11, 14, 46, 703000), 'scheduler/memory_enqueued': 2, 'start_time': datetime.datetime(2012, 7, 13, 11, 14, 45, 500000)} 2012-07-13 19:14:46+0800 [dmoz] INFO: Spider closed (finished) 2012-07-13 19:14:46+0800 [scrapy] INFO: Dumping global stats: {}
注意包含 [dmoz]的行 ,那对应着咱们的爬虫。你能够看到start_urls中定义的每一个URL都有日志行。由于这些URL是起始页面,因此他们没有引用(referrers),因此在每行的末尾你会看到 (referer: <None>).
有趣的是,在咱们的 parse 方法的做用下,两个文件被建立:分别是 Books 和 Resources,这两个文件中有URL的页面内容。
发生了什么事情?
Scrapy为爬虫的 start_urls属性中的每一个URL建立了一个 scrapy.http.Request 对象 ,并将爬虫的parse 方法指定为回调函数。
这些 Request首先被调度,而后被执行,以后经过parse()方法,scrapy.http.Response 对象被返回,结果也被反馈给爬虫。
提取Item
选择器介绍
咱们有不少方法从网站中提取数据。Scrapy 使用一种叫作 XPath selectors的机制,它基于 XPath表达式。若是你想了解更多selectors和其余机制你能够查阅资料http://doc.scrapy.org/topics/selectors.html#topics-selectors
这是一些XPath表达式的例子和他们的含义
这只是几个使用XPath的简单例子,可是实际上XPath很是强大。若是你想了解更多XPATH的内容,咱们向你推荐这个XPath教程http://www.w3schools.com/XPath/default.asp
为了方便使用XPaths,Scrapy提供XPathSelector 类, 有两种口味能够选择, HtmlXPathSelector (HTML数据解析) 和XmlXPathSelector (XML数据解析)。 为了使用他们你必须经过一个 Response 对象对他们进行实例化操做。你会发现Selector对象展现了文档的节点结构。所以,第一个实例化的selector必与根节点或者是整个目录有关 。
Selectors 有三种方法
尝试在shell中使用Selectors
为了演示Selectors的用法,咱们将用到 内建的Scrapy shell,这须要系统已经安装IPython (一个扩展python交互环境) 。
附IPython下载地址:http://pypi.python.org/pypi/ipython#downloads
要开始shell,首先进入项目顶层目录,而后输入
T:\tutorial>scrapy shell http://www.dmoz.org/Computers/Programming/Languages/Python/Books/
输出结果相似这样:
2012-07-16 10:58:13+0800 [scrapy] INFO: Scrapy 0.14.4 started (bot: tutorial) 2012-07-16 10:58:13+0800 [scrapy] DEBUG: Enabled extensions: TelnetConsole, CloseSpider, WebService, CoreStats, SpiderState 2012-07-16 10:58:13+0800 [scrapy] DEBUG: Enabled downloader middlewares: HttpAuthMiddleware, DownloadTimeoutMiddleware, UserAgentMiddleware, RetryMiddleware, DefaultHeadersMiddleware, RedirectMiddleware, CookiesMiddleware, HttpCompressionMiddleware, ChunkedTransferMiddleware, DownloaderStats 2012-07-16 10:58:13+0800 [scrapy] DEBUG: Enabled spider middlewares: HttpErrorMiddleware, OffsiteMiddleware, RefererMiddleware, UrlLengthMiddleware, DepthMiddleware 2012-07-16 10:58:13+0800 [scrapy] DEBUG: Enabled item pipelines: 2012-07-16 10:58:13+0800 [scrapy] DEBUG: Telnet console listening on 0.0.0.0:6023 2012-07-16 10:58:13+0800 [scrapy] DEBUG: Web service listening on 0.0.0.0:6080 2012-07-16 10:58:13+0800 [dmoz] INFO: Spider opened 2012-07-16 10:58:18+0800 [dmoz] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> (referer: None) [s] Available Scrapy objects: [s] hxs <HtmlXPathSelector xpath=None data=u'<html><head><meta http-equiv="Content-Ty'> [s] item {} [s] request <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> [s] response <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> [s] settings <CrawlerSettings module=<module 'tutorial.settings' from 'T:\tutorial\tutorial\settings.pyc'>> [s] spider <DmozSpider 'dmoz' at 0x1f68230> [s] Useful shortcuts: [s] shelp() Shell help (print this help) [s] fetch(req_or_url) Fetch request (or URL) and update local objects [s] view(response) View response in a browser WARNING: Readline services not available or not loaded.WARNING: Proper color support under MS Windows requires the pyreadline library. You can find it at: http://ipython.org/pyreadline.html Gary's readline needs the ctypes module, from: http://starship.python.net/crew/theller/ctypes (Note that ctypes is already part of Python versions 2.5 and newer). Defaulting color scheme to 'NoColor'Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] Type "copyright", "credits" or "license" for more information. IPython 0.13 -- An enhanced Interactive Python. ? -> Introduction and overview of IPython's features. %quickref -> Quick reference. help -> Python's own help system. object? -> Details about 'object', use 'object??' for extra details. In [1]:
Shell载入后,你将得到回应,这些内容被存储在本地变量 response 中,因此若是你输入response.body 你将会看到response的body部分,或者输入response.headers 来查看它的 header部分。
Shell也实例化了两种selectors,一个是解析HTML的 hxs 变量,一个是解析 XML 的 xxs 变量。咱们来看看里面有什么:
In [1]: hxs.path('//title') Out[1]: [<HtmlXPathSelector xpath='//title' data=u'<title>Open Directory - Computers: Progr'>] In [2]: hxs.path('//title').extract() Out[2]: [u'<title>Open Directory - Computers: Programming: Languages: Python: Books</title>'] In [3]: hxs.path('//title/text()') Out[3]: [<HtmlXPathSelector xpath='//title/text()' data=u'Open Directory - Computers: Programming:'>] In [4]: hxs.path('//title/text()').extract() Out[4]: [u'Open Directory - Computers: Programming: Languages: Python: Books'] In [5]: hxs.path('//title/text()').re('(\w+):') Out[5]: [u'Computers', u'Programming', u'Languages', u'Python'] In [6]:
提取数据
如今咱们尝试从网页中提取数据。
你能够在控制台输入 response.body, 检查源代码中的 XPaths 是否与预期相同。然而,检查HTML源代码是件很枯燥的事情。为了使事情变得简单,咱们使用Firefox的扩展插件Firebug。更多信息请查看Using Firebug for scraping 和Using Firefox for scraping.
txw1958注:事实上我用的是Google Chrome的Inspect Element功能,并且能够提取元素的XPath。
检查源代码后,你会发现咱们须要的数据在一个 <ul>元素中,并且是第二个<ul>。
咱们能够经过以下命令选择每一个在网站中的 <li> 元素:
hxs.path('//ul/li')
而后是网站描述:
hxs.path('//ul/li/text()').extract()
网站标题:
hxs.path('//ul/li/a/text()').extract()
网站连接:
hxs.path('//ul/li/a/@href').extract()
如前所述,每一个path()调用返回一个selectors列表,因此咱们能够结合path()去挖掘更深的节点。咱们将会用到这些特性,因此:
sites = hxs.path('//ul/li') for site in sites: title = site.path('a/text()').extract() link = site.path('a/@href').extract() desc = site.path('text()').extract() print title, link, desc
Note
更多关于嵌套选择器的内容,请阅读Nesting selectors 和 Working with relative XPaths
将代码添加到爬虫中:
txw1958注:代码有修改,绿色注释掉的代码为原教程的,你懂的
from scrapy.spider import BaseSpider from scrapy.selector import HtmlXPathSelector class DmozSpider(BaseSpider): name = "dmoz" allowed_domains = ["dmoz.org"] start_urls = [ "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/", "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/" ] def parse(self, response): hxs = HtmlXPathSelector(response) sites = hxs.path('//fieldset/ul/li') #sites = hxs.path('//ul/li') for site in sites: title = site.path('a/text()').extract() link = site.path('a/@href').extract() desc = site.path('text()').extract() #print title, link, desc print title, link
如今咱们再次抓取dmoz.org,你将看到站点在输出中被打印 ,运行命令
T:\tutorial>scrapy crawl dmoz
使用条目(Item)
Item 对象是自定义的python字典,使用标准字典相似的语法,你能够获取某个字段(即以前定义的类的属性)的值:
>>> item = DmozItem() >>> item['title'] = 'Example title' >>> item['title'] 'Example title'
Spiders但愿将其抓取的数据存放到Item对象中。为了返回咱们抓取数据,spider的最终代码应当是这样:
from scrapy.spider import BaseSpider from scrapy.selector import HtmlXPathSelector from tutorial.items import DmozItem class DmozSpider(BaseSpider): name = "dmoz" allowed_domains = ["dmoz.org"] start_urls = [ "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/", "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/" ] def parse(self, response): hxs = HtmlXPathSelector(response) sites = hxs.path('//fieldset/ul/li') #sites = hxs.path('//ul/li') items = [] for site in sites: item = DmozItem() item['title'] = site.path('a/text()').extract() item['link'] = site.path('a/@href').extract() item['desc'] = site.path('text()').extract() items.append(item) return items
如今咱们再次抓取 :
2012-07-16 14:52:36+0800 [dmoz] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> {'desc': [u'\n\t\t\t\n\t', u' \n\t\t\t\n\t\t\t\t\t\n - Free Python books and tutorials.\n \n'], 'link': [u'http://www.techbooksforfree.com/perlpython.shtml'], 'title': [u'Free Python books']} 2012-07-16 14:52:36+0800 [dmoz] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Books/> {'desc': [u'\n\t\t\t\n\t', u' \n\t\t\t\n\t\t\t\t\t\n - Annotated list of free online books on Python scripting language. Topics range from beginner to advanced.\n \n '], 'link': [u'http://www.freetechbooks.com/python-f6.html'], 'title': [u'FreeTechBooks: Python Scripting Language']} 2012-07-16 14:52:36+0800 [dmoz] DEBUG: Crawled (200) <GET http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/> (referer: None) 2012-07-16 14:52:36+0800 [dmoz] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/> {'desc': [u'\n\t\t\t\n\t', u' \n\t\t\t\n\t\t\t\t\t\n - A directory of free Python and Zope hosting providers, with reviews and ratings.\n \n'], 'link': [u'http://www.oinko.net/freepython/'], 'title': [u'Free Python and Zope Hosting Directory']} 2012-07-16 14:52:36+0800 [dmoz] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/> {'desc': [u'\n\t\t\t\n\t', u' \n\t\t\t\n\t\t\t\t\t\n - Features Python books, resources, news and articles.\n \n'], 'link': [u'http://oreilly.com/python/'], 'title': [u"O'Reilly Python Center"]} 2012-07-16 14:52:36+0800 [dmoz] DEBUG: Scraped from <200 http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/> {'desc': [u'\n\t\t\t\n\t', u' \n\t\t\t\n\t\t\t\t\t\n - Resources for reporting bugs, accessing the Python source tree with CVS and taking part in the development of Python.\n\n'], 'link': [u'http://www.python.org/dev/'], 'title': [u"Python Developer's Guide"]}
保存抓取的数据
保存信息的最简单的方法是经过Feed exports,命令以下:
T:\tutorial>scrapy crawl dmoz -o items.json -t json
全部抓取的items将以JSON格式被保存在新生成的items.json 文件中
在像本教程同样的小型项目中,这些已经足够。然而,若是你想用抓取的items作更复杂的事情,你能够写一个 Item Pipeline(条目管道)。由于在项目建立的时候,一个专门用于条目管道的占位符文件已经随着items一块儿被创建,目录在tutorial/pipelines.py。若是你只须要存取这些抓取后的items的话,就不须要去实现任何的条目管道。
结束语
本教程简要介绍了Scrapy的使用,可是许多其余特性并无说起。
对于基本概念的了解,请访问Basic concepts
咱们推荐你继续学习Scrapy项目的例子dirbot,你将从中受益更深,该项目包含本教程中提到的dmoz爬虫。
Dirbot项目位于https://github.com/scrapy/dirbot
项目包含一个README文件,它详细描述了项目的内容。
若是你熟悉git,你能够checkout它的源代码。或者你能够经过点击Downloads下载tarball或zip格式的文件。
另外这有一个代码片段共享网站,里面共享内容包括爬虫,中间件,扩展应用,脚本等。网站名字叫Scrapy snippets,有好的代码要记得共享哦:-)
文件源码附件稍后上传……