天天看点

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

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

CrawlSpider

LinkExtractors

Rule

scrapy

框架中的类,其中

CrawlSpider

Spider

的派生类,具有更多的方法和功能,

LinkExtractor

类是用作提取链接的,

Rule

表示的是爬取的规则。

CrawlSpider

CrawlSpider

Spider

的派生类,

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

LinkExtractor

是从网页(

scrapy.http.Response

)中抽取会被

follow

的链接的对象。

LinkExtractor

CrawlSpider

类(在

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

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

其类的定义如下:

link_extractor

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

callback

:是一个

callable

string

(该

Spider

中同名的函数将会被调用)。从

link_extractor

中每获取到链接时将会调用该函数。该回调函数接收一个

response

作为其第一个参数,并返回一个包含

Item

以及

Request

对象(或者这两者的子类)的列表。

cb_kwargs

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

follow

:是一个

boolean

值,指定了根据该规则从

response

提取的链接是否需要跟进。如果

callback

None

follow

默认设置

True

,否则默认

False

process_links

:是一个

callable

string

(该

Spider

中同名的函数将会被调用)。从

link_extrator

中获取到链接列表时将会调用该函数。该方法主要是用来过滤。

process_request

:是一个

callable

string

(该

spider

中同名的函数都将会被调用)。该规则提取到的每个

request

时都会调用该函数。该函数必须返回一个

request

或者

None

。用来过滤

request

CrawlSpider的爬虫示例

CrawlSpider以

58租房 上海

为例,爬取的数据有

标题,房子,地址,价格等

。具体看下面代码:

  1. 创建项目

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

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

items.py

创建一个Item,默认会创建一个

ZufangItem

类,在

ZufangItem

类中定义字段

import scrapy

class 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, Rule
from scrapy.linkextractor import LinkExtractor
from zufang58.items import Zufang58Item


class 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()')[].extract().strip()
            room = element.xpath('.//div[@class="des"]/p[@class="room"]')[].extract()
            zone = element.xpath('.//div[@class="des"]/p[@class="add"]/a[1]/text()')[].extract()
            address = element.xpath('.//div[@class="des"]/p[@class="add"]/a[last()]/text()')[].extract()
            money = element.xpath('.//div[@class="money"]/b/text()')[].extract()
            type = element.xpath('.//div[@class="des"]/p[last()]/@class')[].extract()
            if type == "add" or type == "room":
                type = element.xpath('.//div[@class="des"]/div[@class="jjr"]/@class')[].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': ,
}
           
  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

文件中。