2015-01-16 7 views
8
class AljazeeraSpider(XMLFeedSpider): 
    name = "aljazeera" 
    allowed_domains = ["aljazeera.com"] 
    start_urls = [ 
     'http://www.aljazeera.com/', 
    ] 

    def parse(self, response): 
     hxs = HtmlXPathSelector(response) # The xPath selector 
     titles = hxs.select('//div[contains(@class,"SkyScrapperBoxes")]/div[contains(@class,"skyscLines")]') 
     if not titles: 
      MailNotify().send_mail("Aljazeera", "Scraper Report") 

     items = [] 
     for titles in titles: 
      item = NewsItem() 
      item['title'] = escape(''.join(titles.select('a/text()').extract())) 
      item['link'] = "http://www.aljazeera.com" + escape(''.join(titles.select('a/@href').extract())) 
      item['description'] = '' 
      item = Request(item['link'], meta={'item': item}, callback=self.parse_detail) 
      items.append(item) 

     return items 

    def parse_detail(self, response): 
     item = response.meta['item'] 
     sel = HtmlXPathSelector(response) 
     detail = sel.select('//td[@class = "DetailedSummary"]') 
     item['details'] = remove_html_tags(escape(''.join(detail.select('p').extract()))) 
     item['location'] = '' 
     published_date = sel.select('//span[@id = "ctl00_cphBody_lblDate"]') 
     item['published_date'] = escape(''.join(published_date.select('text()').extract())) 

     return item 

Attualmente sto lavorando su Scrapy per eseguire la scansione del sito Web. Ho qualche conoscenza su unittest in python. Ma, come posso scrivere l'unittest per verificare che il collegamento funzioni, e item['location'], item['details'] restituiscono il valore o no? Ho appreso il contratto Scrapy ma non riesco a capire nulla. Quindi, come si può scrivere l'unittest in questo caso?Come posso iniziare a scrivere il test unitario in web Scrapy usando python?

risposta

12

Se stiamo parlando in modo specifico di come testare gli spider (non pipeline o caricatori), allora quello che abbiamo fatto è stato fornito "una risposta falsa" da un file HTML locale. Esempio di codice:

import os 
from scrapy.http import Request, TextResponse 

def fake_response(file_name=None, url=None): 
    """Create a Scrapy fake HTTP response from a HTML file""" 
    if not url: 
     url = 'http://www.example.com' 

    request = Request(url=url) 
    if file_name: 
     if not file_name[0] == '/': 
      responses_dir = os.path.dirname(os.path.realpath(__file__)) 
      file_path = os.path.join(responses_dir, file_name) 
     else: 
      file_path = file_name 

     file_content = open(file_path, 'r').read() 
    else: 
     file_content = '' 

    response = TextResponse(url=url, request=request, body=file_content, 
          encoding='utf-8') 
    return response 

Poi, nella tua classe TestCase, chiamare la funzione fake_response() e dei mangimi la risposta al parse() callback:

from unittest.case import TestCase 

class MyTestCase(TestCase): 
    def setUp(self): 
     self.spider = MySpider() 

    def test_parse(self): 
     response = fake_response('input.html') 
     item = self.spider.parse(response) 
     self.assertEqual(item['title'], 'My Title') 
     # ... 

A parte questo, si dovrebbe assolutamente iniziare a utilizzare Item Loaders con i processori di input e output - questo aiuterebbe a ottenere una migliore modularità e, quindi, l'isolamento - il ragno produrrebbe solo istanze di oggetti, la preparazione dei dati e la modifica verrebbero incapsulati all'interno della latta r, che testare separatamente.