2、定义Item
Item是保存爬取到的数据的容器,其使用方法和python字典类似,并且提供了额外保护机制来避免拼写错误导致的未定义字段错误。
首先根据需要从目标网站获取到的数据对item进行建模。 比如我们需要从网站dmoz中获取名字,url,以及网站的描述。 对此,在item中定义相应的字段。当我们爬取到相应的数据后,就存储到这个类里面。编辑 tutorial 目录中的 items.py 文件:
Copy import scrapy
class Data(scrapy.Item): # 根据目标数据定义的类,用来存储目标数据,主要是字典的形式,如data['title'] = '2'
title = scrapy.Field()
link = scrapy.Field()
desc = scrapy.Field()
3、编写爬虫
spider是用户编写用于从单个网站(或者一些网站)爬取数据的类,其中包含了一个用于下载的初始URL,如何跟进网页中的链接以及如何分析页面中的内容,提取生成Item的方法。
为了创建一个spider,必须继承scrapy.spider类,并且定义以下属性
name: 用于区别Spider。 该名字必须是唯一的 ,您不可以为不同的Spider设定相同的名字。
start_urls: 包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。 后续的URL则从初始的URL获取到的数据中提取。
parse() 是spider的一个方法。 被调用时,每个初始URL完成下载后生成的 Response 对象将会作为唯一的参数传递给该函数。该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的 Request 对象。
以下是一个例子,应该保存在tutorial/spiders目录下的dmoz_spider.py文件中
Copy import scrapy
class DmozSpider(scrapy.Spider):
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]
with open(filename, 'wb') as f:
f.write(response.body)
进入项目的根目录,执行下列命令启动spider
该命令用于启动爬去dmoz.org的spider,之后得到输出
查看包含 [dmoz] 的输出,可以看到输出的log中包含定义在 start_urls 的初始URL,并且与spider中是一一对应的。在log中可以看到其没有指向其他页面( (referer:None) )。除此之外,更有趣的事情发生了。就像我们 parse 方法指定的那样,有两个包含url所对应的内容的文件被创建了: Book , Resources 。
4、过程
Scrapy为Spider的 start_urls 属性中的每个URL创建了 scrapy.Request 对象,并将 parse 方法作为回调函数 (callback)赋值给了Request。Request对象经过调度,执行生成 scrapy.http.Response 对象并送回给spider parse() 方法。
5、提取Item
从网页中提取数据有很多方法。Scrapy使用了一种基于 XPath 和 CSS 表达式机制: Scrapy Selectors 。为了配合XPath,Scrapy除了提供了 Selector 之外,还提供了方法来避免每次从response中提取数据时生成selector的麻烦。Selector有四个基本的方法:
xpath(): 传入xpath表达式,返回该表达式所对应的所有节点的selector list列表
css(): 传入CSS表达式,返回该表达式所对应的所有节点的selector list列表
extract(): 序列化该节点为unicode字符串并返回list
re(): 根据传入的正则表达式对数据进行提取,返回unicode字符串list列表
6、提取数据
这部分的工作主要是分析目标数据在源码中的位置,由此确定合适Xpath表达式,借助浏览器,如chrome的检查功能,可以简化这部分的工作。
网站的信息
Copy response.xpath('//ul/li')
网站的描述
Copy response.xpath('//ul/li/text()').extract()
等等,每个 .xpath() 调用返回selector组成的list,因此我们可以拼接更多的 .xpath() 来进一步获取某个节点
Copy for sel in response.xpath('//ul/li'):
title = sel.xpath('a/text()').extract()
link = sel.xpath('a/@href').extract()
desc = sel.xpath('text()').extract()
print title, link, desc
然后在spider中加入这段代码
Copy import scrapy
class DmozSpider(scrapy.Spider):
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):
for sel in response.xpath('//ul/li'):
title = sel.xpath('a/text()').extract()
link = sel.xpath('a/@href').extract()
desc = sel.xpath('text()').extract()
print title, link, desc
7、使用item
Item对象是自定义的python字典,您可以使用标准的字段语法来货渠道每个字段的值。(字段即是我们之前用Field赋值的属性)
Copy item = DmozItem()
item['title'] = 'Example title'
item['title']
'Example title'
一般来说,Spider将会将爬取到的数据以 Item 对象返回。所以为了将爬取的数据返回,我们最终的代码将是
Copy 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/Books/",
"http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/"
]
def parse(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
8、保存数据
最简单存储爬取的数据的方式是使用Feed exports
Copy scrapy crawl dmoz -o items.json
该命令将采用 JSON 格式对爬取的数据进行序列化,生成 items.json 文件。在类似本篇教程里这样小规模的项目中,这种存储方式已经足够。 如果需要对爬取到的item做更多更为复杂的操作,您可以编写 Item Pipeline 。 类似于我们在创建项目时对Item做的,用于您编写自己的 tutorial/pipelines.py 也被创建。 不过如果您仅仅想要保存item,您不需要实现任何的pipeline
三、命令行工具
Scrapy是通过 scrapy 命令行工具进行控制的。 这里我们称之为 “Scrapy tool” 以用来和子命令进行区分。 对于子命令,我们称为 “command” 或者 “Scrapy commands”。Scrapy tool 针对不同的目的提供了多个命令,每个命令支持不同的参数和选项。
1、创建项目
Copy scrapy startproject myproject
# myproject是任意设定项目名称
2、工具命令
查看单个命令的详细内容
查看所有可用命令
Scrapy提供了两种类型的命令。一种必须在Scrapy项目中运行(针对项目(Project-specific)的命令),另外一种则不需要(全局命令)。全局命令在项目中运行时的表现可能会与在非项目中运行有些许差别(因为可能会使用项目的设定)
Copy startproject
settings
runspider
shell
fetch
view
version
Copy crawl
check
list
edit
parse
genspider
deploy
bench
3、具体命令
可以使用提前定义好的模板来生成spider
示例
Copy scrapy genspider -l
Available templates:
basic
crawl
csvfeed
xmlfeed
scrapy genspider -d basic
import scrapy
class $classname(scrapy.Spider):
name = "$name"
allowed_domains = ["$domain"]
start_urls = (
'http://www.$domain/',
)
def parse(self, response):
pass
scrapy genspider -t basic example example.com
Created spider 'example' using template 'basic' in module:
mybot.spiders.example
请注意这四种可选的模板
使用spider进行爬取
Copy scrapy crawl myspider
运行contract检查?
Copy scrapy check -l
first_spider
* parse
* parse_item
second_spider
* parse
* parse_item
scrapy check
[FAILED] first_spider:parse_item
>>> 'RetailPricex' field is missing
[FAILED] first_spider:parse
>>> Returned 92 requests, expected 0..4
列出当前项目中所有可用的spider。每行输出一个spider
Copy scrapy list
spider1
spider2
使用 EDITOR 中设定的编辑器编辑给定的spider
该命令仅仅是提供一个快捷方式。开发者可以自由选择其他工具或者IDE来编写调试spider。
使用Scrapy下载器(downloader)下载给定的URL,并将获取到的内容送到标准输出。
该命令以spider下载页面的方式获取页面。例如,如果spider有 USER_AGENT 属性修改了 User Agent,该命令将会使用该属性。
因此,您可以使用该命令来查看spider如何获取某个特定页面。
该命令如果非项目中运行则会使用默认Scrapy downloader设定。
Copy $ scrapy fetch --nolog http://www.example.com/some/page.html
[ ... html content here ... ]
$ scrapy fetch --nolog --headers http://www.example.com/
{'Accept-Ranges': ['bytes'],
'Age': ['1263 '],
'Connection': ['close '],
'Content-Length': ['596'],
'Content-Type': ['text/html; charset=UTF-8'],
'Date': ['Wed, 18 Aug 2010 23:59:46 GMT'],
'Etag': ['"573c1-254-48c9c87349680"'],
'Last-Modified': ['Fri, 30 Jul 2010 15:30:18 GMT'],
'Server': ['Apache/2.2.3 (CentOS)']}
在浏览器中打开给定的URL,并以Scrapy spider获取到的形式展现。 有些时候spider获取到的页面和普通用户看到的并不相同。 因此该命令可以用来检查spider所获取到的页面,并确认这是您所期望的。
Copy $ scrapy view http://www.example.com/some/page.html
[ ... browser starts ... ]
以给定的URL(如果给出)或者空(没有给出URL)启动Scrapy shell。
Copy $ scrapy shell http://www.example.com/some/page.html
[ ... scrapy shell starts ... ]
获取给定的URL并使用相应的spider分析处理。如果您提供 --callback 选项,则使用spider的该方法处理,否则使用 parse
支持的选项:
--spider=SPIDER: 跳过自动检测spider并强制使用特定的spider
--a NAME=VALUE: 设置spider的参数(可能被重复)
--callback or -c: spider中用于解析返回(response)的回调函数
--pipelines: 在pipeline中处理item
--rules or -r: 使用 CrawlSpider 规则来发现用来解析返回(response)的回调函数
--noitems: 不显示爬取到的item
--nolinks: 不显示提取到的链接
--nocolour: 避免使用pygments对输出着色
--depth or -d: 指定跟进链接请求的层次数(默认: 1)
--verbose or -v: 显示每个请求的详细信息
Copy $ scrapy parse http://www.example.com/ -c parse_item
[ ... scrapy log lines crawling example.com spider ... ]
>>> STATUS DEPTH LEVEL 1 <<<
# Scraped Items ------------------------------------------------------------
[{'name': u'Example item',
'category': u'Furniture',
'length': u'12 cm'}]
# Requests -----------------------------------------------------------------
[]
在未创建项目的情况下,运行一个编写在Python文件中的spider。
Copy $ scrapy runspider myspider.py
[ ... spider starts crawling ... ]
获取Scrapy的设定
,在项目中运行时,该命令将会输出项目的设定值,否则输出Scrapy默认设定。
Copy $ scrapy settings --get BOT_NAME
scrapybot
$ scrapy settings --get DOWNLOAD_DELAY
0