Als ich versuchte, einen Unit-Test für Scrapy zu schreiben, war das etwas Besonderes und ich hatte nicht viele Informationen, also habe ich es zusammengefasst. Aufgrund der Eigenschaften des Crawlers, dass es sicher ist, den HTML-Code jederzeit zu ändern, ist es meiner Meinung nach besser, ihn hauptsächlich zu verwenden, um die Crawlzeit zum Zeitpunkt der Implementierung zu verkürzen, als die Gültigkeitsprüfung. (* Dies ist hauptsächlich ein Artikel über Spider-Unit-Tests) (* Tests wie Pipeline liegen außerhalb des Bereichs, da sie normalerweise mit unittest usw. geschrieben werden können.)
TL;DR;
Verwenden Sie Spinnenverträge
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
"""
Ich denke, es ist schnell, den folgenden Beispielcode zu sehen. (Python3.6.2, Scrapy 1.4.0)
myblog.py
def parse_list(self, response):
"""Listenbildschirm-Analyseprozess
@url http://www.rhoboro.com/index2.html
@returns item 0 0
@returns requests 0 10
"""
for detail in response.xpath('//div[@class="post-preview"]/a/@href').extract():
yield Request(url=response.urljoin(detail), callback=self.parse_detail)
Verträge können durch Erstellen eigener Unterklassen verlängert werden. Registrieren Sie die erstellten Verträge in settings.py.
self.args
adjust_request_args (self, kwags)
Methodepre_process (self, response)
Methodepost_process (self, output)
Methodecontracts.py
# -*- coding: utf-8 -*-
from scrapy.contracts import Contract
from scrapy.exceptions import ContractFail
class ItemValidateContract(Contract):
"""Überprüfen Sie, ob der Artikel den Erwartungen entspricht
Weil sich das Akquisitionsergebnis jederzeit ändern kann
Ich denke, es ist am besten, nur dort zu testen, wo Sie unveränderliche Werte erwarten.
Sollte ich mehr als fehlende Elemente mit Pipeline überprüfen?
"""
name = 'item_validate' #Dieser Name ist der Name in der Dokumentzeichenfolge
def post_process(self, output):
item = output[0]
if 'title' not in item:
raise ContractFail('title is invalid.')
class CookiesContract(Contract):
"""Auf Anfrage(kratzig)Vertrag zum Hinzufügen von Cookies
@cookies key1 value1 key2 value2
"""
name = 'cookies'
def adjust_request_args(self, kwargs):
# self.Konvertieren Sie Argumente in das Wörterbuchformat und setzen Sie Cookies ein
kwargs['cookies'] = {t[0]: t[1]
for t in zip(self.args[::2], self.args[1::2])}
return kwargs
Der Code auf der Seite, die dies verwendet, sieht folgendermaßen aus.
settings.py
...
SPIDER_CONTRACTS = {
'item_crawl.contracts.CookiesContract': 10,
'item_crawl.contracts.ItemValidateContract': 20,
}
...
myblog.py
def parse_detail(self, response):
"""Detailbildschirm-Analyseprozess
@url http://www.rhoboro.com/2017/08/05/start-onomichi.html
@returns item 1
@scrapes title body tags
@item_validate
@cookies index 2
"""
item = BlogItem()
item['title'] = response.xpath('//div[@class="post-heading"]//h1/text()').extract_first()
item['body'] = response.xpath('//article').xpath('string()').extract_first()
item['tags'] = response.xpath('//div[@class="tags"]//a/text()').extract()
item['index'] = response.request.cookies['index']
yield item
Führen Sie mit "Scrapy Check Spidername" aus. Offensichtlich ist es schneller als das Ausprobieren des Scrapy-Crawler-Spinnennamens, da nur die angegebene Seite gecrawlt wird.
(venv) [alpaca]~/github/scrapy/crawler/crawler % scrapy check my_blog [master:crawler]
.....
----------------------------------------------------------------------
Ran 5 contracts in 8.919s
OK
in
parse_detail ())(venv) [alpaca]~/github/scrapy/crawler/crawler % scrapy check my_blog [master:crawler]
...FF
======================================================================
FAIL: [my_blog] parse_detail (@scrapes post-hook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/rhoboro/github/scrapy/venv/lib/python3.6/site-packages/scrapy/contracts/__init__.py", line 134, in wrapper
self.post_process(output)
File "/Users/rhoboro/github/scrapy/venv/lib/python3.6/site-packages/scrapy/contracts/default.py", line 89, in post_process
raise ContractFail("'%s' field is missing" % arg)
scrapy.exceptions.ContractFail: 'title' field is missing
======================================================================
FAIL: [my_blog] parse_detail (@item_validate post-hook)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/Users/rhoboro/github/scrapy/venv/lib/python3.6/site-packages/scrapy/contracts/__init__.py", line 134, in wrapper
self.post_process(output)
File "/Users/rhoboro/github/scrapy/crawler/crawler/contracts.py", line 18, in post_process
raise ContractFail('title is invalid.')
scrapy.exceptions.ContractFail: title is invalid.
----------------------------------------------------------------------
Ran 5 contracts in 8.552s
FAILED (failures=2)
Übrigens hier im Fehlerfall. (In diesem Moment habe ich vergessen, settings.py zu erwähnen.) Um ehrlich zu sein, gibt es zu wenig Informationen und es ist schwierig.
(venv) [alpaca]~/github/scrapy/crawler/crawler % scrapy check my_blog [master:crawler]
Unhandled error in Deferred:
----------------------------------------------------------------------
Ran 0 contracts in 0.000s
OK
Recommended Posts