Scrapy框架学习(四)----CrawlSpider、LinkExtractors、Rule及爬虫示例

来源:互联网 发布:大月氏人 人种 知乎 编辑:程序博客网 时间:2024/05/16 08:50

Scrapy框架学习(四)—-CrawlSpider、LinkExtractors、Rule及爬虫示例

CrawlSpiderLinkExtractorsRulescrapy框架中的类,其中CrawlSpiderSpider的派生类,具有更多的方法和功能,LinkExtractor类是用作提取链接的,Rule表示的是爬取的规则

CrawlSpider

CrawlSpiderSpider的派生类,Spider类的设计原则是只爬取start_urls中的url,而CrawlSpider类定义了一些规则(rules)来提供跟进链接(link)的方便机制,从爬取的网页中获取link并继续爬取的工作更适合。

CrawlSpider除了Spider继承过来的属性外,还提供了一个新的属性:

rules

包含一个或多个Rule对象的集合。每个Rule对爬取网站的动作定义了特定规则。Rule对象会在下面介绍。

如果多个Rule匹配了相同的链接,则根据他们在本属性中被定义的顺序,第一个会被使用。

CrawlSpider也提供了一个可复写的方法:

parse_start_url(response)

当start_url的请求返回时,该方法被调用。该方法分析最初的返回值并必须返回一个Item对象或一个Request对象或者一个可迭代的包含二者的对象

当编写爬虫规则时,请避免使用parse 作为回调函数。 由于CrawlSpider使用parse 方法来实现其逻辑,如果 您覆盖了parse 方法,CrawlSpider将会运行失败。


LinkExtractor

class scrapy.linkextractors.LinkExtractor

LinkExtractor是从网页(scrapy.http.Response)中抽取会被follow的链接的对象。

LinkExtractorCrawlSpider类(在Scrapy可用)中使用, 通过一套规则,但你也可以用它在你的Spider中,即使你不是从CrawlSpider继承的子类, 因为它的目的很简单: 提取链接

每个LinkExtractor有唯一的公共方法是 extract_links(),它接收一个 Response 对象,并返回一个 scrapy.link.Link 对象。

Link Extractors要实例化一次,并且 extract_links 方法会根据不同的 response 调用多次提取链接。

class scrapy.linkextractors.LinkExtractor(    allow = (),    deny = (),    allow_domains = (),    deny_domains = (),    deny_extensions = None,    restrict_xpaths = (),    tags = ('a','area'),    attrs = ('href'),    canonicalize = True,    unique = True,    process_value = None)

主要参数:

allow:满足括号中”正则表达式”的值会被提取,如果为空,则全部匹配。

deny:与这个正则表达式(或正则表达式列表)不匹配的url一定不提取

allow_domains:会被提取的连接的domains

deny_domains:一定不会被提取链接的domains。

restrict_xpaths:使用xpath表达式,和allow共同作用过滤链接。


Rule

Rule对象是一个爬取规则的类。

其类的定义如下:

class scrapy.contrib.spiders.Rule(link_extractor,callback=None,cb_kwargs=None,follow=None,process_links=None,process_request=None)

link_extractor:是一个Link Extractor对象。其定义了如何从爬取到的页面提取链接。

callback:是一个callablestring(该Spider中同名的函数将会被调用)。从link_extractor中每获取到链接时将会调用该函数。该回调函数接收一个response作为其第一个参数,并返回一个包含Item以及Request对象(或者这两者的子类)的列表。

cb_kwargs:包含传递给回调函数的参数(keyword argument)的字典。

follow:是一个boolean值,指定了根据该规则从response提取的链接是否需要跟进。如果callbackNonefollow默认设置True,否则默认False

process_links:是一个callablestring(该Spider中同名的函数将会被调用)。从link_extrator中获取到链接列表时将会调用该函数。该方法主要是用来过滤

process_request:是一个callablestring(该spider中同名的函数都将会被调用)。该规则提取到的每个request时都会调用该函数。该函数必须返回一个request或者None。用来过滤request

CrawlSpider的爬虫示例

CrawlSpider以58租房 上海为例,爬取的数据有标题,房子,地址,价格等。具体看下面代码:

  1. 创建项目

在项目的父目录创建项目,执行如下命令:

scrapy startproject zufang58
  1. 定义需要爬取的字段

items.py创建一个Item,默认会创建一个ZufangItem类,在ZufangItem类中定义字段

import scrapyclass Zufang58Item(scrapy.Item):    # 标题    title = scrapy.Field()    # 房间    room = scrapy.Field()    # 区域    zone = scrapy.Field()    # 地址    address = scrapy.Field()    # 价格    money = scrapy.Field()    # 发布信息的类型,品牌公寓,经纪人,个人    type = scrapy.Field()
  1. 编写Spider类

在spiders目录创建一个zufang58_spider.py文件,在文件中定义一个名为ZuFang58Spider继承CrawlSpider,代码如下。

from scrapy.spider import CrawlSpider, Rulefrom scrapy.linkextractor import LinkExtractorfrom zufang58.items import Zufang58Itemclass ZuFang58Spider(CrawlSpider):    # spider的唯一名称    name = 'zufang58'    # 开始爬取的url    start_urls = ["http://sh.58.com/chuzu/"]    # 从页面需要提取的url 链接(link)    links = LinkExtractor(allow="sh.58.com/chuzu/pn\d+")    # 设置解析link的规则,callback是指解析link返回的响应数据的的方法    rules = [Rule(link_extractor=links, callback="parseContent", follow=True)]    def parseContent(self, response):        """        解析响应的数据,获取需要的数据字段        :param response: 响应的数据        :return:        """        # 根节点 //ul[@class="listUl"]/li[@logr]        # title: .//div[@class="des"]/h2/a/text()        # room: .//div[@class="des"]/p[@class="room"]/text()        # zone: .//div[@class="des"]/p[@class="add"]/a[1]/text()        # address: .//div[@class="des"]/p[@class="add"]/a[last()]/text()        # money: .//div[@class="money"]/b/text()        # type: # .//div[@class="des"]/p[last()]/@class     # 如果是add,room  .//div[@class="des"]/div[@class="jjr"]/@class        for element in response.xpath('//ul[@class="listUl"]/li[@logr]'):            title = element.xpath('.//div[@class="des"]/h2/a/text()')[0].extract().strip()            room = element.xpath('.//div[@class="des"]/p[@class="room"]')[0].extract()            zone = element.xpath('.//div[@class="des"]/p[@class="add"]/a[1]/text()')[0].extract()            address = element.xpath('.//div[@class="des"]/p[@class="add"]/a[last()]/text()')[0].extract()            money = element.xpath('.//div[@class="money"]/b/text()')[0].extract()            type = element.xpath('.//div[@class="des"]/p[last()]/@class')[0].extract()            if type == "add" or type == "room":                type = element.xpath('.//div[@class="des"]/div[@class="jjr"]/@class')[0].extract()            item = Zufang58Item()            item['title'] = title            item['room'] = room            item['zone'] = zone            item['address'] = address            item['money'] = money            item['type'] = type            yield item
  1. 编写pipeline(管道)

在pipeline.py文件中,创建Zufang58Pipeline类,实现process_item()方法。如:

class Zufang58Pipeline(object):    def __init__(self):        self.file = open('zufang58.json', mode='w', encoding='utf-8')    def process_item(self, item, spider):        jsondata = json.dumps(dict(item), ensure_ascii=False) + "\n"        self.file.write(jsondata)        return item    def close_spider(self, spider):        self.file.close()
  1. 配置pipeline管道和请求头字段
DEFAULT_REQUEST_HEADERS = {    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.89 Safari/537.36',    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',    'Accept-Language': 'en',}...ITEM_PIPELINES = {    'zufang58.pipelines.Zufang58Pipeline': 300,}
  1. 执行爬虫命令
scrapy crawl zufang58

我们可以在控制台中可以看到有很多的log输出。如果我们想把log保存到文件。可以在setting.py配置。

  1. 配置logging

Scrapy提供5层logging级别:

  • CRITICAL:严重错误(critical)
  • ERROR:一般错误(regular errors)
  • WARNING:警告信息(warning messages)
  • INFO:一般信息(informational messages)
  • DEBUG: 调试信息(debugging messages)

通过在setting.py中进行以下设置可以被用来配置logging:

  • LOG_ENABLED 默认: True,启用logging
  • LOG_ENCODING 默认: utf-8,logging使用的编码
  • LOG_FILE 默认: None,在当前目录里创建logging输出文件的文件名
  • LOG_LEVEL 默认: DEBUG,log的最低级别
  • LOG_STDOUT 默认: False,如果为 True,进程所有的标准输出(及错误)将会被重定向到log中。例如,执行 print “hello” ,其将会在Scrapy log中显示。

在settings.py配置logging

LOG_FILE = 'zufang58.log'LOG_LEVEL = 'DEBUG'

就可以将log输出到zufang58.log文件中。

阅读全文
0 0