Scrapy-spiders(爬虫)

来源:互联网 发布:qq旋风mac 迅雷下载 编辑:程序博客网 时间:2024/05/17 05:55

爬虫(Spiders)

Spider 类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider 就是您定义爬取的动作及分析某个网页(或者是有些网页)的地方。

对于spider,爬取循环做着下面的事情:

  1. 首先生成抓取第一个URL的初始 request,request 下载完成后生成 response ,然后指定对 response 要使用的回调函数。

    通过调用 start_requests() 方法(默认情况下)为 start_urls 中指定的URL生成初始的 Request 以及将 parse方法作为请求的回调函数。

  2. 在回调函数中,您将解析 Response(网页)并返回带有提取的数据的 dict,Item对象,Request 对象或这些对象的可迭代容器。这些请求还将包含回调(可能是相同的),然后由 Scrapy 下载,然后由指定的回调处理它们的响应。

  3. 在回调函数中,您通常使用 选择器 来解析页面内容(但您也可以使用BeautifulSoup,lxml或您喜欢的任何解析器),并使用解析的数据生成 Item。

  4. 最后,从爬虫返回的 Item 通常将持久存储到数据库(在某些 Item Pipeline 中)或使用 Feed导出 写入文件。

虽然这个循环(或多或少)适用于任何种类的 spider,Scrapy 实现了不同种类的默认 spider 用于不同的需求。我们将在这里谈论这些类型。

scrapy.Spider

class scrapy.spiders.Spider

  • 这是最简单的爬虫,每个其他爬虫必须继承该类(包括 Scrapy 自带的一些爬虫,以及你自己写的爬虫)。它不提供任何特殊功能。它只是提供了一个默认的 start_requests() 实现,它读取并请求爬虫的 start_urls 属性,并为每个结果响应调用爬虫的 parse 方法。

    name

    定义此爬虫名称的字符串。爬虫名称是爬虫如何由 Scrapy 定位(和实例化),因此它必须是唯一的。但是,您可以生成多个相同的爬虫实例(instance),这没有任何限制。 name是spider最重要的属性,而且是必须的。

    如果蜘蛛抓取单个网站(single domain),一个常见的做法是以该网站(domain)(加或不加 后缀 )来命名spider。 例如,如果爬取 mywebsite.com ,该爬虫通常会被命名为 mywebsite 。

    注意!

    在Python 2中,这必须是ASCII。

    allowed_domains

    可选。包含了此爬虫允许抓取的域的列表。 Requests for URLs not belonging to the domain names specified in this list won’t be followed if OffsiteMiddleware is enabled.

    start_urls

    URL列表。当没有指定特定 URL 时,爬虫将从从该列表中开始抓取。因此,爬取的第一个页面将是这里列出的某个 URL。后续的 URL 将根据包含在起始 URL 中的数据连续生成。

    custom_settings

    该设置是一个dict。运行此爬虫时改设置会覆盖项目级的设置。因为设置在实例化(instantiation)之前更新,所以它必须定义为类属性。

    有关可用内置设置的列表,请参阅:[内置设置参考]。

    crawler

    此属性由初始化类后的类方法 from_crawler() 设置,并链接到此爬虫实例绑定到的 Crawler 对象。

    Crawlers在项目中封装了很多组件,作为单一入口访问(例如扩展,中间件,信号管理器等)。有关详情,请参阅 Crawler API。

    settings

    运行此爬虫的配置。这是一个 Settings 实例,请参 设置 来了解详细介绍 。

    logger

    Python Logger 使用 Spider 的 name 创建。您可以使用它通过它发送日志消息,如从记录日志记录。

    from_crawler

    这是 Scrapy 用来创建 spider 的类方法。

    您可能不需要直接复写它,因为默认实现充当 __init __() 方法的代理,使用给定的参数 args 和命名参数 kwargs 调用它。

    尽管如此,此方法会在新实例中设置 crawler 和 settings 属性,以便稍后在爬虫代码中访问它们。

    参数:

    • crawler(Crawler 实例) -spider将绑定到的crawler
    • args(list) - 传递给 __init __() 方法的参数
    • kwargs(dict) - 传递给 __init __() 方法的关键字参数

    start_requests

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

    当 spider 启动时且未指定特定的 URL 时,Scrapy 会调用该方法。如果指定了特定的 URL,则使用 make_requests_from_url() 来创建 Request 对象。此方法仅被调用一次,因此将其作为生成器实现是安全的。

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

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

    class MySpider(scrapy.Spider):  name = 'myspider'  def start_requests(self):      return [scrapy.FormRequest("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)。

    parse(response)

    当response没有指定回调函数时,这是Scrapy用来处理下载的response的默认方法。parse 方法负责处理response并返回所抓取的数据以及(/或)跟进的URL。Spider 对其他的Request的回调函数也有相同的要求。

    此方法以及任何其他Requestd的回调函数必须返回一个可迭代的 Request 或 dict 或 [Item] 对象。

    参数:response(Response) - 用于分析的response

    log(message[, level, component])

    通过 Spider 的 logger 发送日志消息,保留向后兼容性。有关详细信息,请参阅 Logging from Spiders

    closed(reason)

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

让我们看一个例子:

import scrapyclass 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):        self.logger.info('A response from %s just arrived!', response.url)

在单个回调函数中返回多个Request以及Item的例子:

import scrapyclass 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):        for h3 in response.xpath('//h3').extract():            yield {"title": h3}        for url in response.xpath('//a/@href').extract():            yield scrapy.Request(url, callback=self.parse)

除了 start_urls ,你也可以直接使用 start_requests() ; 您也可以使用 Items 来给予数据更多的结构性(give data more structure):

import scrapyfrom myproject.items import MyItemclass MySpider(scrapy.Spider):    name = 'example.com'    allowed_domains = ['example.com']    def start_requests(self):        yield scrapy.Request('http://www.example.com/1.html', self.parse)        yield scrapy.Request('http://www.example.com/2.html', self.parse)        yield scrapy.Request('http://www.example.com/3.html', self.parse)    def parse(self, 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 arguments

Spider 可以接收参数来修改其行为。spider 参数的一些常见用法是定义起始URL或限制要爬取一部分网站,但它们可用于配置spider 的任何功能。

Spider参数使用 -a 选项通过 crawl 命令传递。例如:

scrapy crawl myspider -a category=electronics

spider 可以在他们的 init 方法中访问参数:

import scrapyclass MySpider(scrapy.Spider):    name = 'myspider'    def __init__(self, category=None, *args, **kwargs):        super(MySpider, self).__init__(*args, **kwargs)        self.start_urls = ['http://www.example.com/categories/%s' % category]        # ...

默认的 init 方法将获取任何spider参数,并将它们作为 spider 的属性。上面的例子也可以写成如下:

import scrapyclass MySpider(scrapy.Spider):    name = 'myspider'    def start_requests(self):        yield scrapy.Request('http://www.example.com/categories/%s' % self.category)

请记住,蜘蛛参数只能是字符串。蜘蛛自己不会做任何解析。如果要从命令行设置 start_urls 属性,则必须使用 ast.literal_eval 或 json.loads 之类将它解析为列表,并将它设置为属性,然后将其设置为属性。否则,你会导致迭代一个 start_urls 字符串(一个非常常见的python陷阱),导致每个字符被看作一个单独的url。

有效的用例是通过 HttpAuthMiddleware 设置 http auth 证书或 通过 UserAgentMiddleware 设置 user agent:

scrapy crawl myspider -a http_user=myuser -a http_pass=mypassword -a user_agent=mybot

Spider 参数也可以通过 Scrapyd schedule.json API 传递。请参阅 Scrapyd文档 。

Generic Spiders

Scrapy 自带一些有用的通用爬虫,你可以将自己的爬虫作为它们的子类。他们的目的是为一些常见的抓取案例提供方便的功能,例如根据某些规则跟踪网站上的所有链接,从 Sitemaps 抓取或解析XML / CSV Feed。

对于在下面的爬虫中使用的示例,我们假设你有一个项目,在 myproject.items 模块中声明一个 TestItem

import scrapyclass TestItem(scrapy.Item):    id = scrapy.Field()    name = scrapy.Field()    description = scrapy.Field()

CrawlSpider

class scrapy.spiders.CrawlSpider

  • 这是最常用的爬行常规网站的spider,因为它通过定义一组规则为跟进链接提供了一个方便的机制。它可能不是完全适合您的特定网站或项目,但它有足够多的几种通用情况,因此您可以以此为起点,根据需要覆盖更多的自定义功能,当然也可以实现自己的spider。

    除了从Spider继承的属性(您必须指定),这个类支持一个新的属性:

    rules

    它是一个(或多个)Rule 对象的列表。每个 Rule 定义用于爬取网址的特定行为。Rule 对象如下所述。如果多个规则匹配相同的链接,则将根据它们在此属性中定义的顺序使用第一个。

该spider也提供了一个可复写(overrideable)的方法:

parse_start_url(response)

对于 start_urls 中url所对应的 response 调用此方法。它允许解析初始响应,并且必须返回 Item 对象,Request 对象或包含其中任何对象的iterable。

爬取规则(Crawling rules)

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

  • link_extractor 是一个 链接提取器(Link Extractor)对象,它定义如何从要爬取的页面提取链接。

    callback 是一个 callable 或 string(在这种情况下,该spider中同名的函数将会被调用),使用 link_extractor 从 Response 对象中提取的每个链接将会调用该函数。该回调接函数收一个 response 作为它的第一个参数,并且必须返回一个包含 Item 及(或)[Request] 对象(或它们的任何子类)的列表。

    警告!

    当编写爬虫规则时,避免使用 parse 作为回调,因为 CrawlSpider 使用parse方法本身来实现其逻辑。因此,如果您覆盖 parse 方法,crawl spider 将会运行失败。

    [cb_kwargs] 是一个包含要传递给回调函数(keyword argument)的关键字参数的dict。

    [follow] 是一个布尔值,指定了根据该规则从response提取的链接是否需要跟进。如果 [callable] 为 None,则默认为 True,否则默认为 False。

    [process_links] 是一个 callable 或 string(在这种情况下,该spider中同名的函数将会被调用),使用 link_extractor 从 Response 对象中提取的每个链接列表调用它。这主要用于过滤目的。

    [process_request] 是一个 callable 或 string(在这种情况下,该spider中同名的函数将会被调用),它将被此规则提取的每个 request 调用,并且必须返回一个 request 或None(过滤出 request)。

CrawlSpider示例

现在让我们来看看一个带有 rule 的 CrawlSpider 示例:

import scrapyfrom scrapy.spiders import CrawlSpider, Rulefrom scrapy.linkextractors import LinkExtractorclass MySpider(CrawlSpider):    name = 'example.com'    allowed_domains = ['example.com']    start_urls = ['http://www.example.com']    rules = (        # Extract links matching 'category.php' (but not matching 'subsection.php')        # and follow links from them (since no callback means follow=True by default).        Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),        # Extract links matching 'item.php' and parse them with the spider's method 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

该spider将从example.com的首页开始爬取,获取category以及item的链接并对后者使用 parse_item 方法。 当item获得返回(response)时,将使用XPath处理HTML并生成一些数据填入 Item 中。

XMLFeedSpider

XMLFeedSpider example

CSVFeedSpider

CSVFeedSpider example

SitemapSpider

SitemapSpider examples