【问题标题】:Create unit-test for method of scrapy CrawlSpider为scrapy CrawlSpider的方法创建单元测试
【发布时间】:2016-04-28 14:26:51
【问题描述】:

最初的问题

我正在编写一个 CrawlSpider 类(使用 scrapy 库)并依靠大量 scrapy 异步魔法 使其工作。在这里,精简:

class MySpider(CrawlSpider):
    rules = [Rule(LinkExtractor(allow='myregex'), callback='parse_page')]
    # some other class attributes

    def __init__(self, *args, **kwargs):
        super(MySpider, self).__init__(*args, **kwargs)
        self.response = None
        self.loader = None

    def parse_page_section(self):
        soup = BeautifulSoup(self.response.body, 'lxml')
        # Complicated scraping logic using BeautifulSoup
        self.loader.add_value(mykey, myvalue)

    # more methods parsing other sections of the page
    # also using self.response and self.loader

    def parse_page(self, response):
        self.response = response
        self.loader = ItemLoader(item=Item(), response=response)
        self.parse_page_section()
        # call other methods to collect more stuff
        self.loader.load_item()

类属性rule 告诉我的蜘蛛跟随某些链接并在网页下载后跳转到回调函数。我的目标是在不运行爬虫甚至不发出真正的 HTTP 请求的情况下测试名为 parse_page_section 的解析方法。

我尝试了什么

本能地,我转向mock 图书馆。我理解你如何模拟一个函数来测试它是否被调用(使用哪些参数以及是否有任何副作用......),但这不是我想要的。我想实例化一个假对象 MySpider 并分配足够的属性以便能够在其上调用 parse_page_section 方法。

在上面的例子中,我需要一个response 对象来实例化我的ItemLoader,特别是一个self.response.body 属性来实例化我的BeautifulSoup。原则上,我可以制作这样的假对象:

from argparse import Namespace

my_spider = MySpider(CrawlSpider)
my_spider.response = NameSpace(body='<html>...</html>')

这适用于 BeautifulSoup 类,但我需要添加更多属性来创建 ItemLoader 对象。对于更复杂的情况,它会变得丑陋且难以管理。

我的问题

这是完全正确的方法吗?我在网上找不到类似的例子,所以我认为我的方法在更基本的层面上可能是错误的。任何见解将不胜感激。

【问题讨论】:

  • @ChrisP 感谢您的编辑。我没有将scrapy 标签放在首位,因为我认为这个问题通常与单元测试有关。
  • 这绝对是一般的单元测试,但是做大量爬虫的人可能对单元测试爬虫有一些独特的见解。
  • 在这种特殊的CrawlSpider 案例中,我可以假装响应对象。手工操作很困难,但这有帮助吗? requests-mock.readthedocs.io/en/latest/overview.html。这是一个好方法吗?

标签: python unit-testing mocking scrapy


【解决方案1】:

你见过Spiders Contracts吗?

这使您无需大量代码即可测试蜘蛛的每个回调。例如:

def parse(self, response):
    """ This function parses a sample response. Some contracts are mingled
    with this docstring.

    @url http://www.amazon.com/s?field-keywords=selfish+gene
    @returns items 1 16
    @returns requests 0 0
    @scrapes Title Author Year Price
    """

使用check 命令运行合约检查。

看看这个answer,如果你想要更大的东西。

【讨论】:

  • 我认为进行现实生活(集成)测试而不是单元测试是有意义的,因为网站本身可以改变。从本质上讲,您的单元测试工作的事实并不能确保您的抓取工作。感谢您的建议。
  • 尽管如此,单元测试仍然有价值,至少在编码时进行完整性检查。您提供的另一个答案(stackoverflow.com/questions/6456304/scrapy-unit-testing/… 展示了如何通过实际使用 scrapy RequestResponse 对象以更好的方式伪造响应对象。不错的提示。
猜你喜欢
  • 2012-12-01
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 2011-09-21
  • 1970-01-01
  • 2011-08-23
  • 2019-12-01
  • 1970-01-01
相关资源
最近更新 更多