爬虫Scrapy系列

(三) Spider

2019-05-04  本文已影响0人  iamlightsmile

Spider是用户编写用于从单个网站(或者一些网站)爬取数据的类。

其包含了一个用于下载的初始URL,如何跟进网页中的链接以及如何分析页面中的内容, 提取生成 item 的方法。

Spider的创建

为了创建一个Spider,您必须继承 scrapy.Spider 类, 且定义以下三个属性:

Spider示例

示例1:

import scrapy

class MySpider(scrapy.Spider):
    name = '[example.com](http://example.com/)'
    allowed_domains = ['[example.com](http://example.com/)']
    start_urls = [
        '[http://www.example.com/1.html](http://www.example.com/1.html)',
        '[http://www.example.com/2.html](http://www.example.com/2.html)',
        '[http://www.example.com/3.html](http://www.example.com/3.html)',
    ]

    def parse(self, response):
        self.log('A response from %s just arrived!' % response.url)

示例2:

import scrapy
from myproject.items import MyItem

class MySpider(scrapy.Spider):
    name = '[example.com](http://example.com/)'
    allowed_domains = ['[example.com](http://example.com/)']
    start_urls = [
        '[http://www.example.com/1.html](http://www.example.com/1.html)',
        '[http://www.example.com/2.html](http://www.example.com/2.html)',
        '[http://www.example.com/3.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)

Spider的业务循环

对spider来说,爬取的循环类似下文:

  1. 以初始的URL初始化Request,并设置回调函数。 当该request下载完毕并返回时,将生成response,并作为参数传给该回调函数。

    spider中初始的request是通过调用 start_requests() 来获取的。 start_requests() 读取 start_urls 中的URL, 并以 parse 为回调函数生成 Request

  2. 在回调函数内分析返回的(网页)内容,返回 Item 对象或者 Request 或者一个包括二者的可迭代容器。 返回的Request对象之后会经过Scrapy处理,下载相应的内容,并调用设置的callback函数(函数可相同)。

  3. 在回调函数内,您可以使用 选择器(Selectors) (您也可以使用BeautifulSoup, lxml 或者您想用的任何解析器) 来分析网页内容,并根据分析的数据生成item。

  4. 最后,由spider返回的item将被存到数据库(由某些 Item Pipeline 处理)或使用 Feed exports 存入到文件中。

虽然该循环对任何类型的spider都(多少)适用,但Scrapy仍然为了不同的需求提供了多种默认spider。

Spider类其他属性方法

allowed_domains

可选。包含了spider允许爬取的域名(domain)列表(list)。 当 OffsiteMiddleware 启用时, 域名不在列表中的URL不会被跟进。

start_requests()

该方法必须返回一个可迭代对象(iterable)。该对象包含了spider用于爬取的第一个Request。

当spider启动爬取并且未制定URL时,该方法被调用。 当指定了URL时,make_requests_from_url() 将被调用来创建Request对象。 该方法仅仅会被Scrapy调用一次,因此您可以将其实现为生成器。

该方法的默认实现是使用 start_urls 的url生成Request。

如果您想要修改最初爬取某个网站的Request对象,您可以重写(override)该方法。 例如,如果您需要在启动时以POST登录某个网站,你可以这么写:

def start_requests(self):
    return [scrapy.FormRequest("[http://www.example.com/login](http://www.example.com/login)",
                               formdata={'user': 'john', 'pass': 'secret'},
                               callback=self.logged_in)]

def logged_in(self, response):
    # here you would extract links to follow and return Requests for
    # each of them, with another callback
    pass

make_requests_from_url(url)

该方法接受一个URL并返回用于爬取的 Request 对象。 该方法在初始化request时被 start_requests() 调用,也被用于转化url为request。

默认未被复写(overridden)的情况下,该方法返回的Request对象中, parse() 作为回调函数,dont_filter参数也被设置为开启。 (详情参见 Request).

closed(reason)

当spider关闭时,该函数被调用。 该方法提供了一个替代调用signals.connect()来监听 spider_closed 信号的快捷方式。

Spider子类

CrawlSpider

class scrapy.contrib.spiders.CrawlSpider
爬取一般网站常用的spider。其定义了一些规则(rule)来提供跟进link的方便的机制。 也许该spider并不是完全适合您的特定网站或项目,但其对很多情况都使用。 因此您可以以其为起点,根据需求修改部分方法。当然您也可以实现自己的spider。

XMLFeedSpider

class scrapy.contrib.spiders.XMLFeedSpider
XMLFeedSpider被设计用于通过迭代各个节点来分析XML源(XML feed)。 迭代器可以从 iternodes , xml , html 选择。 鉴于 xml 以及 html 迭代器需要先读取所有DOM再分析而引起的性能问题, 一般还是推荐使用 iternodes 。 不过使用 html 作为迭代器能有效应对错误的XML。

CSVFeedSpider

class scrapy.contrib.spiders.CSVFeedSpider
该spider除了其按行遍历而不是节点之外其他和XMLFeedSpider十分类似。 而其在每次迭代时调用的是 parse_row()

SitemapSpider

class scrapy.contrib.spiders.SitemapSpider
SitemapSpider使您爬取网站时可以通过 Sitemaps 来发现爬取的URL。

其支持嵌套的sitemap,并能从 robots.txt 中获取sitemap的url。

上一篇下一篇

猜你喜欢

热点阅读