2013-07-22 1 views
1

Предположим, у меня есть следующие структуры сайта:Почему мой определенный предмет не заселен и не хранится у Scrapy?

  1. Начальные URL: http://thomas.loc.gov/cgi-bin/query/z?c107:H.R. % s: где % s - это индекс 1-50 (образец для иллюстративных целей).
  2. «1-й слой»: Билль-текст или ссылка на несколько версий ...
  3. «2-й слой»: Билль Текст со ссылкой на «Версия для печати» (обычный текст).

Конечная цель сценария:

  1. Перемещаться по начальной URL-адресов; URL-адрес анализа, заголовок & Тело; сохраняя их в файле starts.txt
  2. Извлечь ссылки «1-го уровня» с самого начала URL-адресов; перейдите по этим ссылкам; URL-адрес анализа, заголовок & Тело; сохраните их в файле bills.txt
  3. Извлечь ссылки «2-го слоя» из тела URL «1-го уровня»; перейдите по этим ссылкам; URL анализа, заголовок & Кузов; сохранить их в файл versions.txt

Предположим, что у меня есть следующий сценарий:

from scrapy.item import Item, Field 
from scrapy.contrib.spiders import CrawlSpider, Rule 
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor 
from scrapy.selector import HtmlXPathSelector 

class StartItem(Item): 
    url = Field() 
    title = Field() 
    body = Field() 

class BillItem(Item): 
    url = Field() 
    title = Field() 
    body = Field() 

class VersionItem(Item): 
    url = Field() 
    title = Field() 
    body = Field() 

class Lrn2CrawlSpider(CrawlSpider): 
    name = "lrn2crawl" 
    allowed_domains = ["thomas.loc.gov"] 
    start_urls = ["http://thomas.loc.gov/cgi-bin/query/z?c107:H.R.%s:" % bill for bill in xrange(000001,00050,00001) ### Sample of 40 bills; Total range of bills is 1-5767 

    ] 

    rules = (
      # Extract links matching /query/D fragment (restricting tho those inside the content body of the url); follow; & scrape all bill text. 
      # and follow links from them (since no callback means follow=True by default). 
      # Desired result: scrape all bill text & in the event that there are multiple versions, follow them & parse. 
      Rule(SgmlLinkExtractor(allow=(r'/query/D'), restrict_xpaths=('//div[@id="content"]')), callback='parse_bills', follow=True), 

      # Extract links in the body of a bill-version & follow them. 
      #Desired result: scrape all version text & in the event that there are multiple sections, follow them & parse. 
      Rule(SgmlLinkExtractor(allow=(r'/query/C'), restrict_xpaths=('//table/tr/td[2]/a/@href')), callback='parse_versions', follow=True) 
     ) 

    def parse_start_url(self, response): 
     hxs = HtmlXPathSelector(response) 
     starts = hxs.select('//div[@id="content"]') 
     scraped_starts = [] 
     for start in starts: 
      scraped_start = StartItem() ### Start object defined previously 
      scraped_start['url'] = response.url 
      scraped_start['title'] = start.select('//h1/text()').extract() 
      scraped_start['body'] = response.body 
      scraped_starts.append(scraped_start) 
      with open('starts.txt', 'a') as f: 
       f.write('url: {0}, title: {1}, body: {2}\n'.format(scraped_start['url'], scraped_start['title'], scraped_start['body'])) 
     return scraped_starts 

    def parse_bills(self, response): 
     hxs = HtmlXPathSelector(response) 
     bills = hxs.select('//div[@id="content"]') 
     scraped_bills = [] 
     for bill in bills: 
      scraped_bill = BillItem() ### Bill object defined previously 
      scraped_bill['url'] = response.url 
      scraped_bill['title'] = bill.select('//h1/text()').extract() 
      scraped_bill['body'] = response.body 
      scraped_bills.append(scraped_bill) 
      with open('bills.txt', 'a') as f: 
       f.write('url: {0}, title: {1}, body: {2}\n'.format(scraped_bill['url'], scraped_bill['title'], scraped_bill['body'])) 
     return scraped_bills 

    def parse_versions(self, response): 
     hxs = HtmlXPathSelector(response) 
     versions = hxs.select('//div[@id="content"]') 
     scraped_versions = [] 
     for version in versions: 
      scraped_version = VersionItem() ### Version object defined previously 
      scraped_version['url'] = response.url 
      scraped_version['title'] = version.select('//h1/text()').extract() 
      scraped_version['body'] = response.body 
      scraped_versions.append(scraped_version) 
      with open('versions.txt', 'a') as f: 
       f.write('url: {0}, title: {1}, body: {2}\n'.format(scraped_version['url'], scraped_version['title'], scraped_version['body'])) 
     return scraped_versions 

Этот сценарий, кажется, делает все, что я хочу, для навигации к «второй слой» кроме ссылок и разбор элементов (URL, заголовок & Body) этих сайтов. Другими словами, Scrapy не сканирует и не анализирует мой «2-й слой».

Чтобы еще раз повторить мой вопрос: почему Scrapy не заполняет мой VersionItem и не выводит его в нужный файл: version.txt?

ответ

1

Проблема в настройке restrict_xpaths на втором SgmlLinkExtractor. Измените его на:

restrict_xpaths=('//div[@id="content"]',) 

Надеюсь, что это поможет.

Смежные вопросы