您的位置:首页 > 编程语言 > Python开发

Python爬虫框架Scrapy 学习笔记 8----Spider

2015-01-10 20:11 916 查看
什么是爬虫?
从逻辑角度讲,爬虫对应一个树。树枝是网页,树叶是感兴趣的信息。
当我们从一个URL出发查找感兴趣的信息时,当前URL返回的内容可能包含我们感兴趣的信息,也可能包含另一个可能包含我们感兴趣的信息的URL。一个爬虫对应一次信息搜索,信息搜索过程会建立起一棵树。



scrapy.Spider这个类提供了接口,允许我们设计整个信息搜索的流程。

给spider传递运行时所需的参数。比如URL ?号后面的参数信息。这些信息可以选择使用crawl -a 命令传递




2. Spider循环
对spider来说,爬取的循环类似下文:以初始的URL初始化Request,并设置回调函数。 当该request下载完毕并返回时,将生成response,并作为参数传给该回调函数。spider中初始的request是通过调用 start_requests() 来获取的。 start_requests() 读取start_urls 中的URL, 并以 parse 为回调函数生成 Request
在回调函数内分析返回的(网页)内容,返回 Item 对象或者 Request 或者一个包括二者的可迭代容器。 返回的Request对象之后会经过Scrapy处理,下载相应的内容,并调用设置的callback函数(函数可相同)。
在回调函数内,您可以使用 选择器(Selectors) (您也可以使用BeautifulSoup, lxml 或者您想用的任何解析器) 来分析网页内容,并根据分析的数据生成item。
最后,由spider返回的item将被存到数据库(由某些 Item Pipeline 处理)或使用 Feed exports 存入到文件中。

Scrapy提供了几种spider的默认实现,下面重点介绍:默认Spider和CrawlSpider

3.最简单的spider(默认的Spider)
用实例属性start_urls中的URL构造Request对象
框架负责执行request
将request返回的response对象传递给parse方法做分析

简化后的源码:
class Spider(object_ref):
"""Base class for scrapy spiders. All spiders must inherit from this
class.
"""

name = None

def __init__(self, name=None, **kwargs):
if name is not None:
self.name = name
elif not getattr(self, 'name', None):
raise ValueError("%s must have a name" % type(self).__name__)
self.__dict__.update(kwargs)
if not hasattr(self, 'start_urls'):
self.start_urls = []

def start_requests(self):
for url in self.start_urls:
yield self.make_requests_from_url(url)

def make_requests_from_url(self, url):
return Request(url, dont_filter=True)

def parse(self, response):
raise NotImplementedError

BaseSpider = create_deprecated_class('BaseSpider', Spider)


一个回调函数返回多个request的例子
import scrapyfrom myproject.items import MyItemclass MySpider(scrapy.Spider):
name = 'example.com'
allowed_domains = ['example.com']
start_urls = [
'http://www.example.com/1.html',
'http://www.example.com/2.html',
'http://www.example.com/3.html',
]

def parse(self, response):
sel = scrapy.Selector(response)
for h3 in response.xpath('//h3').extract():
yield MyItem(title=h3)

for url in response.xpath('//a/@href').extract():
yield scrapy.Request(url, callback=self.parse)
构造一个Request对象只需两个参数: URL和回调函数

4. CrawlSpider

通常我们需要在spider中决定:哪些网页上的链接需要跟进, 哪些网页到此为止,无需跟进里面的链接。CrawlSpider为我们提供了有用的抽象――Rule,使这类爬取任务变得简单。你只需在rule中告诉scrapy,哪些是需要跟进的。
回忆一下我们爬行mininova网站的spider.
class MininovaSpider(CrawlSpider):
name = 'mininova'
allowed_domains = ['mininova.org']
start_urls = ['http://www.mininova.org/yesterday']
rules = [Rule(LinkExtractor(allow=['/tor/\d+']), 'parse_torrent')]

def parse_torrent(self, response):
torrent = TorrentItem()
torrent['url'] = response.url
torrent['name'] = response.xpath("//h1/text()").extract()
torrent['description'] = response.xpath("//div[@id='description']").extract()
torrent['size'] = response.xpath("//div[@id='specifications']/p[2]/text()[2]").extract()
return torrent
上面代码中 rules的含义是:匹配/tor/\d+的URL返回的内容,交给parse_torrent处理,并且不再跟进response上的URL。
官方文档中也有个例子:
rules = (
# 提取匹配 'category.php' (但不匹配 'subsection.php') 的链接并跟进链接(没有callback意味着follow默认为True)
Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),

# 提取匹配 'item.php' 的链接并使用spider的parse_item方法进行分析
Rule(LinkExtractor(allow=('item\.php', )), callback='parse_item'),
)


除了Spider和CrawlSpider外,还有XMLFeedSpider, CSVFeedSpider, SitemapSpider
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: