四、Spider用法

本文转载自以下链接:

https://scrapy-chs.readthedocs.io/zh_CN/latest/topics/spiders.html

https://doc.scrapy.org/en/latest/topics/spiders.html

1、Spiders
对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 存入到文件中。

2、Spider参数
spider参数一般用来定义初始URL或者指定限制爬取网站的部分。 您也可以使用其来配置spider的任何功能。
在运行 crawl 时添加 -a 可以传递Spider参数:
scrapy crawl myspider -a category=electronics

Spider在构造器(constructor)中获取参数:

import scrapy

class MySpider(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]

3、内置Spider参考手册
Spider

class scrapy.spider.Spider

    Spider是最简单的spider。每个其他的spider必须继承自该类(包括Scrapy自带的其他spider以及您自己编写的spider)。
    Spider并没有提供什么特殊的功能。 其仅仅请求给定的 start_urls/start_requests ,并根据返回的结果(resulting responses)调用spider的 parse 方法。

    name
        定义spider名字的字符串(string)。spider的名字定义了Scrapy如何定位(并初始化)spider,所以其必须是唯一的。
        不过您可以生成多个相同的spider实例(instance),这没有任何限制。 name是spider最重要的属性,而且是必须的。
        如果该spider爬取单个网站(single domain),一个常见的做法是以该网站(domain)(加或不加 后缀 )来命名spider。
        例如,如果spider爬取 mywebsite.com ,该spider通常会被命名为 mywebsite 。

    allowed_domains
        可选。包含了spider允许爬取的域名(domain)列表(list)。 当 OffsiteMiddleware 启用时, 域名不在列表中的URL不会被跟进。
        具体咋生效的还不知道
        
    start_urls
        URL列表。当没有制定特定的URL时,spider将从该列表中开始进行爬取。
        因此,第一个被获取到的页面的URL将是该列表之一。 后续的URL将会从获取到的数据中提取。
        
        遍历URL列表中的每个链接均发起Request请求获取返回多个Response   
         
    custom_settings

        A dictionary of settings that will be overridden from the project wide configuration when running this spider.
        It must be defined as a class attribute since the settings are updated before instantiation.
        
        使用的话需要覆盖settings中的相关配置
        class QuotesSpider(scrapy.Spider):
            name = 'quotes'
            allowed_domains = ['quotes.toscrape.com']
            start_urls = ['http://quotes.toscrape.com/']

            custom_settings = {
                'DEFAULT_REQUEST_HEADERS':{
                    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
                    'Accept-Language': 'en',
                }
            }

    crawler
        This attribute is set by the from_crawler() class method after initializating the class, and links to the Crawler object to which this spider instance is bound.
        Crawlers encapsulate a lot of components in the project for their single entry access (such as extensions, middlewares, signals managers, etc). See Crawler API to know more about them.

    settings
        Configuration on which this spider is been ran. This is a Settings instance, see the Settings topic for a detailed introduction on this subject.
        
    logger
        Python logger created with the Spider’s name.
        You can use it to send log messages through it as described on Logging from Spiders.

    from_crawler(crawler, *args, **kwargs)
        This is the class method used by Scrapy to create your spiders.
        You probably won’t need to override this directly, since the default implementation acts as a proxy to the __init__() method, calling it with the given arguments args and named arguments kwargs.
        Nonetheless, this method sets the crawler and settings attributes in the new instance, so they can be accessed later inside the spider’s code.
        参数:    
            crawler (Crawler instance) – crawler to which the spider will be bound
            args (list) – arguments passed to the __init__() method
            kwargs (dict) – keyword arguments passed to the __init__() method
        使用示例:
            def __init__(self, mongo_url, mongo_db,*args, **kwargs):
                super(QuotesSpider, self).__init__(*args, **kwargs)
                self.mongo_uri = mongo_url
                self.mongo_db = mongo_db

            @classmethod
            def from_crawler(cls, crawler):
                """从settings文件获取配置信息"""
                return cls(
                    mongo_url=crawler.settings.get('MONGO_URI'),
                    mongo_db=crawler.settings.get('MONGO_DB')
                )

    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",
                                       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
        
        使用示例:
        import scrapy

        class HttpbinSpider(scrapy.Spider):
            name = 'httpbin'
            allowed_domains = ['httpbin.org']
            start_urls = ['http://httpbin.org/post']

            def start_requests(self):
                yield scrapy.Request(url='http://httpbin.org/post',method='POST',callback=self.parse_post)

            def parse(self, response):
                pass

            def parse_post(self,response):
                print('Hello',response.headers)
                
    make_requests_from_url(url) =>(新版本不再使用)
        该方法接受一个URL并返回用于爬取的 Request 对象。 该方法在初始化request时被 start_requests() 调用,也被用于转化url为request。
        默认未被复写(overridden)的情况下,该方法返回的Request对象中, parse() 作为回调函数,dont_filter参数也被设置为开启。 (详情参见 Request).
        
        源码:
            def start_requests(self):
                cls = self.__class__
                if method_is_overridden(cls, Spider, 'make_requests_from_url'):
                    warnings.warn(
                        "Spider.make_requests_from_url method is deprecated; it "
                        "won't be called in future Scrapy releases. Please "
                        "override Spider.start_requests method instead (see %s.%s)." % (
                            cls.__module__, cls.__name__
                        ),
                    )
                    for url in self.start_urls:
                        yield self.make_requests_from_url(url)
                else:
                    for url in self.start_urls:
                        yield Request(url, dont_filter=True)

            def make_requests_from_url(self, url):
                """ This method is deprecated. """
                return Request(url, dont_filter=True)

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

        该方法及其他的Request回调函数必须返回一个包含 Request 及(或) Item 的可迭代的对象。
        参数:    response (Response) – 用于分析的response

    log(message[, level, component]) =>(新版本用法发生改变)
        使用 scrapy.log.msg() 方法记录(log)message。 log中自动带上该spider的 name 属性。 更多数据请参见 Logging 。
        
        新版本使用示例:https://doc.scrapy.org/en/latest/topics/logging.html?highlight=logger
        import scrapy

        class MySpider(scrapy.Spider):

            name = 'myspider'
            start_urls = ['https://scrapinghub.com']

            def parse(self, response):
                self.logger.info('Parse function called on %s', response.url)

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

Let’s see an example:

    import scrapy


    class 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)

Return multiple Requests and items from a single callback:

    import scrapy

    class 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)

Instead of start_urls you can use start_requests() directly; to give data more structure you can use Items:

    import scrapy
    from myproject.items import MyItem

    class 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)


posted @ 2019-01-21 15:59  哈喽哈喽111111  阅读(1706)  评论(0编辑  收藏  举报