2012-05-15 12 views
6

Tôi đang sử dụng Scrapy, đặc biệt là lớp CrawlSpider của Scrapy để xóa các liên kết web chứa các từ khóa nhất định. Tôi có một danh sách dài start_urls khá dài có các mục nhập từ cơ sở dữ liệu SQLite được kết nối với dự án Django. Tôi muốn lưu các liên kết web được cạo trong cơ sở dữ liệu này.Làm thế nào để truy cập một start_url cụ thể trong một CrawlSpider Scrapy?

Tôi có hai mô hình Django, một cho các url bắt đầu như http://example.com và một cho các liên kết web cạo như http://example.com/website1, http://example.com/website2 vv Tất cả các liên kết web cạo là subsites của một trong những url đầu trong danh sách start_urls.

Mô hình liên kết web có mối quan hệ nhiều với một mô hình url bắt đầu, tức là mô hình liên kết web có một Ngoại ngữ cho mô hình url bắt đầu. Để lưu các liên kết web đã được nạo của tôi một cách chính xác vào cơ sở dữ liệu, tôi cần phải thông báo phương thức 's parse_item() bắt đầu url liên kết web cóp nhặt thuộc về. Làm thế nào tôi có thể làm điều đó? Lớp DjangoItem của Scrapy không giúp ích về mặt này vì tôi vẫn phải xác định url bắt đầu được sử dụng một cách rõ ràng.

Nói cách khác, làm cách nào tôi có thể chuyển url bắt đầu hiện được sử dụng sang phương thức parse_item(), để tôi có thể lưu nó cùng với các liên kết web cóp nhặt phù hợp vào cơ sở dữ liệu? Ý tưởng nào? Cảm ơn trước!

+0

Bạn có thể có trường start_url trong cùng một bảng với bảng liên kết web (như trong DjangoItem bạn đang sử dụng) không?Chắc chắn, nó sẽ tạo ra sự không chuẩn hóa dư thừa nhưng nếu bạn muốn tránh gọi một cách rõ ràng, điều này có thể hữu ích. – zubinmehta

Trả lời

8

Theo mặc định, bạn không thể truy cập url bắt đầu ban đầu.

Nhưng bạn có thể ghi đè phương thức make_requests_from_url và đặt url bắt đầu vào meta. Sau đó, trong một phân tích cú pháp bạn có thể trích xuất nó từ đó (nếu bạn mang lại trong đó phân tích cú pháp phương pháp tiếp theo yêu cầu, đừng quên để chuyển tiếp mà bắt đầu url trong họ).


Tôi chưa từng làm việc với CrawlSpider và có lẽ những gì Maxim gợi ý sẽ làm việc cho bạn, nhưng hãy nhớ rằng response.url có url sau khi chuyển hướng có thể.

Dưới đây là một ví dụ về làm thế nào tôi sẽ làm điều đó, nhưng nó chỉ là một ví dụ (lấy từ các hướng dẫn scrapy) và không được kiểm tra:

class MySpider(CrawlSpider): 
    name = 'example.com' 
    allowed_domains = ['example.com'] 
    start_urls = ['http://www.example.com'] 

    rules = (
     # Extract links matching 'category.php' (but not matching 'subsection.php') 
     # and follow links from them (since no callback means follow=True by default). 
     Rule(SgmlLinkExtractor(allow=('category\.php',), deny=('subsection\.php',))), 

     # Extract links matching 'item.php' and parse them with the spider's method parse_item 
     Rule(SgmlLinkExtractor(allow=('item\.php',)), callback='parse_item'), 
    ) 

    def parse(self, response): # When writing crawl spider rules, avoid using parse as callback, since the CrawlSpider uses the parse method itself to implement its logic. So if you override the parse method, the crawl spider will no longer work. 
     for request_or_item in CrawlSpider.parse(self, response): 
      if isinstance(request_or_item, Request): 
       request_or_item = request_or_item.replace(meta = {'start_url': response.meta['start_url']}) 
      yield request_or_item 

    def make_requests_from_url(self, url): 
     """A method that receives a URL and returns a Request object (or a list of Request objects) to scrape. 
     This method is used to construct the initial requests in the start_requests() method, 
     and is typically used to convert urls to requests. 
     """ 
     return Request(url, dont_filter=True, meta = {'start_url': url}) 

    def parse_item(self, response): 
     self.log('Hi, this is an item page! %s' % response.url) 

     hxs = HtmlXPathSelector(response) 
     item = Item() 
     item['id'] = hxs.select('//td[@id="item_id"]/text()').re(r'ID: (\d+)') 
     item['name'] = hxs.select('//td[@id="item_name"]/text()').extract() 
     item['description'] = hxs.select('//td[@id="item_description"]/text()').extract() 
     item['start_url'] = response.meta['start_url'] 
     return item 

hỏi nếu bạn có thắc mắc. BTW, sử dụng tính năng 'Go to definition' của PyDev, bạn có thể xem các nguồn dữ liệu và tìm hiểu các tham số Request, make_requests_from_url và các lớp và phương pháp khác mong đợi. Nhập mã giúp bạn tiết kiệm thời gian, mặc dù lúc đầu có vẻ khó khăn.

+0

Tôi nghĩ tôi hiểu rõ ý bạn là gì nhưng tôi thực sự không biết cách thực hiện nó. Có lẽ bạn có thể cung cấp một ví dụ ngắn cho thấy phương thức 'make_requests_from_url' thường được sử dụng như thế nào và nó liên quan đến phương thức' parse' như thế nào? Tôi vẫn là người mới bắt đầu. Cảm ơn! – pemistahl

+1

Cảm ơn warwaruk, điều này hoạt động độc đáo. Tuy nhiên, tôi phát hiện ra rằng chỉ có phương thức 'make_requests_from_url' và cấu hình thẻ' meta' của yêu cầu là cần thiết để làm việc này. Tôi không muốn lưu url bắt đầu vào cuối, do đó, nó không có ý nghĩa đối với tôi để đặt nó trong một mục. Dù sao, cảm ơn bạn rất nhiều lần nữa! :) – pemistahl

1

Nếu tôi hiểu chính xác sự cố, Bạn có thể nhận url từ response.url và sau đó viết thư đến item['url'].

Trong Spider: item['url'] = response.url

Và trong đường ống: url = item['url'].

Hoặc đặt response.url vào meta như warvariuc đã viết.

1

Có vẻ như câu trả lời của warvariuc yêu cầu sửa đổi nhỏ như Scrapy 1.3.3: bạn cần ghi đè _parse_response thay vì parse. Ghi đè make_requests_from_url không còn cần thiết nữa.

Các vấn đề liên quan