Scrapy spiders类

Scrapy是python中的爬虫框架,现在来学习spiders类

scrapy.spiders.CrawlSpider

这是用于爬网常规网站的最常用的爬虫类,因为它通过定义一组规则提供了一种用于跟踪链接的便捷机制。它可能不是最适合您的特定网站或项目的方法,但是它在几种情况下都足够通用,因此您可以从中开始并根据需要重写它以获取更多自定义功能,或者只是实现自己的爬虫程序。

除了从Spider继承的属性(必须指定)之外,此类还支持一个新属性:

rules

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

这个类还公开了一个可重写的方法:parse_start_url

调用start_urls响应会使用此方法。它允许解析初始响应,并且必须返回一个 Item对象,一个Request 对象或包含其中任何一个的可迭代对象。

 

实列:

import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor

class 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()').get()
        item['description'] = response.xpath('//td[@id="item_description"]/text()').get()
        item['link_text'] = response.meta['link_text']
        return item

scrapy.spiders.XMLFeedSpider

XMLFeedSpider用于解析XML提要,方法是通过特定的节点名称对XML提要进行迭代。迭代器可以选自:iternodesxml,和htmliternodes出于性能原因,建议使用迭代器,因为xmlhtml迭代器会立即生成整个DOM以便对其进行解析。但是,html当解析带有不良标记的XML时用作迭代器可能会很有用。

要设置迭代器和标记名称,必须定义以下类属性:

iterator

一个字符串,定义要使用的迭代器。可以是:

  • 'iternodes' -基于正则表达式的快速迭代器

  • 'html'-使用的迭代器Selector请记住,这使用DOM解析,并且必须将所有DOM加载到内存中,这对于大型Feed可能是个问题

  • 'xml'-使用的迭代器Selector请记住,这使用DOM解析,并且必须将所有DOM加载到内存中,这对于大型Feed可能是个问题

默认为:'iternodes'

itertag

一个字符串,其中包含要迭代的节点(或元素)的名称。示例:

itertag = 'product'
namespaces

元组列表,这些元组定义了该蜘蛛将处理的该文档中可用的命名空间。的 将被用于自动注册使用的命名空间 的方法。(prefix, uri)prefixuriregister_namespace()

然后,您可以在itertag 属性中指定带有名称空间的节点

例子:

class YourSpider(XMLFeedSpider):

    namespaces = [('n', 'http://www.sitemaps.org/schemas/sitemap/0.9')]
    itertag = 'n:url'
    # ...

除了这些新属性之外,该蜘蛛程序还具有以下可重写方法:

adapt_response回应[来源]

一种在蜘蛛开始解析之前从蜘蛛中间件接收响应的方法。它可以用于在解析响应主体之前对其进行修改。此方法接收响应,并且还返回响应(可以相同也可以是另一个)。

parse_node响应选择器[来源]

对于与提供的标签名称(itertag相匹配的节点,调用此方法接收Selector每个节点的响应和一个 必须重写此方法。否则,您的蜘蛛将无法工作。此方法必须返回一个Item对象,一个 Request对象或包含其中任何一个的可迭代对象。

process_results回应结果[来源]

蜘蛛返回的每个结果(项目或请求)都会调用此方法,并且该方法旨在执行将结果返回到框架核心之前所需的任何最后一次处理,例如设置项目ID。它接收结果列表和产生这些结果的响应。它必须返回结果列表(项目或请求)。

XMLFeedSpider示例

这些蜘蛛非常易于使用,让我们看一个例子:

from scrapy.spiders import XMLFeedSpider
from myproject.items import TestItem

class MySpider(XMLFeedSpider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = ['http://www.example.com/feed.xml']
    iterator = 'iternodes'  # This is actually unnecessary, since it's the default value
    itertag = 'item'

    def parse_node(self, response, node):
        self.logger.info('Hi, this is a <%s> node!: %s', self.itertag, ''.join(node.getall()))

        item = TestItem()
        item['id'] = node.xpath('@id').get()
        item['name'] = node.xpath('name').get()
        item['description'] = node.xpath('description').get()
        return item

基本上,我们要做的就是创建一个Spider,该蜘蛛从给定的源下载供稿start_urls,然后遍历其每个item标签,将其打印出来,然后将一些随机数据存储在中Item

CSVFeedSpider

班级scrapy.spiders.CSVFeedSpider

除了在整个行而不是节点上进行迭代之外,此蜘蛛与XMLFeedSpider非常相似。每次迭代中调用的方法是parse_row()

delimiter

CSV文件中每个字段均带有分隔符的字符串默认为','(逗号)。

quotechar

CSV文件中每个字段的带有附件字符的字符串默认为'"'(引号)。

headers

CSV文件中列名称的列表。

parse_row响应[来源]

接收每个CSV文件提供的(或检测到的)标头的响应和带有键的字典(代表每一行)。该蜘蛛程序还提供了覆盖adapt_responseprocess_results用于预处理和后处理目的的方法的机会

CSVFeedSpider示例

让我们来看一个与上一个示例类似的示例,但是使用一个 CSVFeedSpider

from scrapy.spiders import CSVFeedSpider
from myproject.items import TestItem

class MySpider(CSVFeedSpider):
    name = 'example.com'
    allowed_domains = ['example.com']
    start_urls = ['http://www.example.com/feed.csv']
    delimiter = ';'
    quotechar = "'"
    headers = ['id', 'name', 'description']

    def parse_row(self, response, row):
        self.logger.info('Hi, this is a row!: %r', row)

        item = TestItem()
        item['id'] = row['id']
        item['name'] = row['name']
        item['description'] = row['description']
        return item

scrapy.spiders.SitemapSpider[来源]

SitemapSpider允许您通过使用Sitemaps发现URL来爬网站点 

它支持嵌套站点地图并从robots.txt发现站点地图URL 

sitemap_urls

指向您要抓取其网址的站点地图的网址列表。

您也可以指向robots.txt,然后对其进行解析以从中提取站点地图网址。

sitemap_rules

元组列表,其中:(regex, callback)

  • regex是一个正则表达式,用于匹配从站点地图提取的网址。 regex可以是str或已编译的regex对象。

  • callback是用于处理与正则表达式匹配的url的回调。callback可以是字符串(指示Spider方法的名称)或可调用的。

例如:

sitemap_rules = [('/product/', 'parse_product')]

规则将按顺序应用,并且仅使用第一个匹配的规则。

如果您忽略此属性,则将使用parse回调处理在站点地图中找到的所有网址

sitemap_follow

应遵循的站点地图正则表达式列表。这仅适用于使用指向其他站点地图文件的站点地图索引文件的站点。

默认情况下,将遵循所有站点地图。

指定是否url应遵循一个的替代链接这些是在同一块中传递的另一种语言的同一网站的链接url

例如:

<url>
    <loc>http://example.com/</loc>
    <xhtml:link rel="alternate" hreflang="de" href="http://example.com/de"/>
</url>

随着sitemap_alternate_links设置,这将同时检索的网址。随着 sitemap_alternate_links禁用,只http://example.com/将被检索。

默认设置为sitemap_alternate_links禁用。

sitemap_filter[来源]

这是一个筛选功能,可以覆盖该筛选功能,以根据其属性选择站点地图条目。

例如:

<url>
    <loc>http://example.com/</loc>
    <lastmod>2005-01-01</lastmod>
</url>

我们可以定义一个按日期sitemap_filter过滤函数entries

from datetime import datetime
from scrapy.spiders import SitemapSpider

class FilteredSitemapSpider(SitemapSpider):
    name = 'filtered_sitemap_spider'
    allowed_domains = ['example.com']
    sitemap_urls = ['http://example.com/sitemap.xml']

    def sitemap_filter(self, entries):
        for entry in entries:
            date_time = datetime.strptime(entry['lastmod'], '%Y-%m-%d')
            if date_time.year >= 2005:
                yield entry

entries在2005年及以后的年份会对此进行修改。

条目是从站点地图文档中提取的字典对象。通常,键是标签名称,值是其中的文本。

重要的是要注意:

  • 因为loc属性是必需的,所以没有此标签的条目将被丢弃

  • 备用链接通过键存储在列表中alternate (请参阅参考资料sitemap_alternate_links

  • 命名空间被删除,因此名为的lxml标记{namespace}tagname仅成为tagname

如果省略此方法,将观察站点地图中找到的所有条目,并观察其他属性及其设置。

SitemapSpider示例

最简单的示例:使用parse回调处理通过站点地图发现的所有网址 

from scrapy.spiders import SitemapSpider

class MySpider(SitemapSpider):
    sitemap_urls = ['http://www.example.com/sitemap.xml']

    def parse(self, response):
        pass # ... scrape item here ...

使用某些回调处理某些URL,并使用不同的回调处理其他URL:

from scrapy.spiders import SitemapSpider

class MySpider(SitemapSpider):
    sitemap_urls = ['http://www.example.com/sitemap.xml']
    sitemap_rules = [
        ('/product/', 'parse_product'),
        ('/category/', 'parse_category'),
    ]

    def parse_product(self, response):
        pass # ... scrape product ...

    def parse_category(self, response):
        pass # ... scrape category ...

遵循robots.txt文件中定义的站点地图,并且仅遵循其网址包含的站点地图/sitemap_shop

from scrapy.spiders import SitemapSpider

class MySpider(SitemapSpider):
    sitemap_urls = ['http://www.example.com/robots.txt']
    sitemap_rules = [
        ('/shop/', 'parse_shop'),
    ]
    sitemap_follow = ['/sitemap_shops']

    def parse_shop(self, response):
        pass # ... scrape shop here ...

将SitemapSpider与其他网址来源结合使用:

from scrapy.spiders import SitemapSpider

class MySpider(SitemapSpider):
    sitemap_urls = ['http://www.example.com/robots.txt']
    sitemap_rules = [
        ('/shop/', 'parse_shop'),
    ]

    other_urls = ['http://www.example.com/about']

    def start_requests(self):
        requests = list(super(MySpider, self).start_requests())
        requests += [scrapy.Request(x, self.parse_other) for x in self.other_urls]
        return requests

    def parse_shop(self, response):
        pass # ... scrape shop here ...

    def parse_other(self, response):
        pass # ... scrape other here ...
posted on 2021-05-04 23:12  春秋路人甲  阅读(214)  评论(0)    收藏  举报