官方文档 https://docs.scrapy.org/en/latest/topics/spiders.html#crawlspider
CrawlSpider定义了一组用以提取链接的规则,可以大大简化爬虫的写法。
rules
是一组Rule
对象。每条Rule
定义了抓取网页的方式。如果多条规则匹配到同一链接,根据定义规则的顺序,使用第一个链接。
parse_start_url(response)
用来处理start_urls
的响应,返回的结果必须是Item
对象,或Request
对象,或者是二者的可迭代对象。
代码语言:javascript复制爬取规则
Rule
的用法
scrapy.spiders.Rule(link_extractor,
callback=None,
cb_kwargs=None,
follow=None,
process_links=None,
process_request=None)
link_extractor
是链接抽取对象,它定义了如何抽取链接;
callback
是调回函数,注意不要使用parse
做调回函数;
cb_kwargs
是一个字典,可以将关键字参数传给调回函数;
follow
是一个布尔值,指定要不要抓取链接。如果callback
是None,则follow
默认是True
,否则默认为False
;
process_links
可以对link_extractor
提取出来的链接做处理,主要用于过滤;
process_request
是一个可调用函数,会处理这条Rule提取出来的每个请求,会返回request或None。
代码语言:javascript复制链接抽取
link_extractor
的用法
from scrapy.linkextractors import LinkExtractor
因为用法和LxmlLinkExtractor
相同,官网使用后者说明,LxmlLinkExtractor
是基于lxml的HTMLParser实现的:
class scrapy.linkextractors.lxmlhtml.LxmlLinkExtractor(allow=(),
deny=(),
allow_domains=(),
deny_domains=(),
deny_extensions=None,
restrict_xpaths=(),
restrict_css=(),
tags=('a', 'area'),
attrs=('href', ),
canonicalize=False,
unique=True,
process_value=None,
strip=True)
allow
:(一个或一个列表)出链必须要匹配的正则表达式。如果allow为空,则匹配所有链接;
deny
:(一个或一个列表)出链必须要匹配的正则表达式,以做排除。优先于allow
。如果为空,则不排除任何链接;
allow_domains
:(一个或一个列表)提取链接的域名;
deny_domains
:(一个或一个列表)不提取链接的域名;
deny_extensions
:(一个或一个列表)要忽略的后缀,如果为空,则为包scrapy.linkextractors
中的列表IGNORED_EXTENSIONS
,如下所示:
IGNORED_EXTENSIONS = [
# 图片
'mng', 'pct', 'bmp', 'gif', 'jpg', 'jpeg', 'png', 'pst', 'psp', 'tif',
'tiff', 'ai', 'drw', 'dxf', 'eps', 'ps', 'svg',
# 音频
'mp3', 'wma', 'ogg', 'wav', 'ra', 'aac', 'mid', 'au', 'aiff',
# 视频
'3gp', 'asf', 'asx', 'avi', 'mov', 'mp4', 'mpg', 'qt', 'rm', 'swf', 'wmv',
'm4a', 'm4v', 'flv',
# 办公软件
'xls', 'xlsx', 'ppt', 'pptx', 'pps', 'doc', 'docx', 'odt', 'ods', 'odg',
'odp',
# 其它
'css', 'pdf', 'exe', 'bin', 'rss', 'zip', 'rar',
]
restrict_xpaths
:(一个或一个列表)xpath,定义了从响应文本的哪部分提取链接;
restrict_css
:(一个或一个列表)css,定义了从响应文本的哪部分提取链接;
tags
:(一个或一个列表)用以抽取链接的标签,默认是('a', 'area')
;
attrs
:(一个或一个列表)属性,定义了从响应文本的哪部分提取链接,默认是('href',)
;
canonicalize
:(布尔值)建议设为False;
unique
:(布尔值)是否过滤重复链接;
process_value
:(可调用对象)可以对标签和属性扫描结果做修改,下面是官网给的例子;
# 一个要提取的链接
<a href="javascript:goToPage('../other/page.html'); return false">Link text</a>
# 要提取的是 “../other/page.html”
def process_value(value):
m = re.search("javascript:goToPage('(.*?)'", value)
if m:
return m.group(1)
strip
:(布尔值)默认开启。
官网给的CrawlSpider的例子:
代码语言:javascript复制import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
class MySpider(CrawlSpider):
name = 'example.com'
allowed_domains = ['example.com']
start_urls = ['http://www.example.com']
rules = (
# 提取匹配 'category.php' 的链接 (不匹配 'subsection.php')
# 没有设置callback,则默认follow=True,继续抓取符合该条规则的所有链接
Rule(LinkExtractor(allow=('category.php', ), deny=('subsection.php', ))),
# 提取匹配 'item.php' 的链接,用parse_item方法做解析
Rule(LinkExtractor(allow=('item.php', )), callback='parse_item'),
)
def parse_item(self, response):
self.logger.info('Hi, this is an item page! %s', response.url)
item = scrapy.Item()
item['id'] = response.xpath('//td[@id="item_id"]/text()').re(r'ID: (d )')
item['name'] = response.xpath('//td[@id="item_name"]/text()').extract()
item['description'] = response.xpath('//td[@id="item_description"]/text()').extract()
return item
感觉还是xpath更好用,还是用麦田租房举例子:http://bj.maitian.cn/zfall/PG1
这样写规则就行了
代码语言:javascript复制rules = (
Rule(LinkExtractor(restrict_xpaths='//*[contains(@class,"down_page")]')),
Rule(LinkExtractor(restrict_xpaths='//div[@class="list_title"]/h1/'), callback='parse_item')
)