2012-03-22 34 views
16

Câu hỏi của tôi thực sự là làm thế nào để làm điều tương tự như câu hỏi trước, nhưng trong Scrapy 0.14.Tạo một con nhện phế liệu chung

Using one Scrapy spider for several websites

Về cơ bản, tôi có giao diện đồ họa mà có các thông số như tên miền, từ khóa, tên thẻ, vv và tôi muốn tạo một con nhện chung để thu thập thông những lĩnh vực cho các từ khóa trong các thẻ này. Tôi đã đọc những điều mâu thuẫn, sử dụng các phiên bản cũ của mẩu tin lưu niệm, bằng cách ghi đè lớp trình quản lý nhện hoặc bằng cách tạo động một con nhện. Phương pháp nào được ưa thích và làm cách nào để triển khai và gọi ra giải pháp thích hợp? Cảm ơn trước.

Đây là mã mà tôi muốn làm chung. Nó cũng sử dụng BeautifulSoup. Tôi ghép nó xuống để hy vọng không loại bỏ bất cứ điều gì quan trọng để hiểu nó.

class MySpider(CrawlSpider): 

name = 'MySpider' 
allowed_domains = ['somedomain.com', 'sub.somedomain.com'] 
start_urls = ['http://www.somedomain.com'] 

rules = (
    Rule(SgmlLinkExtractor(allow=('/pages/',), deny=('',))), 

    Rule(SgmlLinkExtractor(allow=('/2012/03/')), callback='parse_item'), 
) 

def parse_item(self, response): 
    contentTags = [] 

    soup = BeautifulSoup(response.body) 

    contentTags = soup.findAll('p', itemprop="myProp") 

    for contentTag in contentTags: 
     matchedResult = re.search('Keyword1|Keyword2', contentTag.text) 
     if matchedResult: 
      print('URL Found: ' + response.url) 

    pass 
+0

Bạn có thể hiển thị mã mà bạn sử dụng cho các giá trị cố định của tên miền, từ khóa, thẻ không? – jfs

+0

Đã thêm mã. Nó sử dụng BeautifulSoup để phân tích cú pháp html. – user1284717

+0

này, đừng quá lười biếng bạn tôi. –

Trả lời

0

Tôi không chắc chắn cách nào được ưa thích, nhưng tôi sẽ cho bạn biết những gì tôi đã làm trong quá khứ. Tôi không chắc chắn rằng đây là cách tốt nhất (hoặc chính xác) để làm điều này và tôi sẽ quan tâm để tìm hiểu những gì người khác nghĩ.

Tôi thường chỉ ghi đè lên các tầng lớp phụ huynh (CrawlSpider) và một trong hai vượt qua trong lập luận và sau đó khởi tạo lớp cha mẹ qua super(MySpider, self).__init__() từ bên trong của riêng tôi init chức năng hoặc tôi kéo trong dữ liệu mà từ một cơ sở dữ liệu mà tôi đã lưu danh sách các liên kết sẽ được thêm vào start_urls trước đó.

1

Thay vì có các biến name, allowed_domains, start_urlsrules gắn vào lớp, bạn nên viết một MySpider.__init__, gọi CrawlSpider.__init__ từ đó đi qua các đối số cần thiết, và thiết lập name, allowed_domains, vv mỗi đối tượng. MyProp và từ khóa cũng phải được đặt trong số __init__ của bạn. Vì vậy, cuối cùng bạn nên có một cái gì đó như dưới đây. Bạn không cần phải thêm name để các đối số, như name được thiết lập bởi BaseSpider chính nó từ kwargs:

class MySpider(CrawlSpider): 

    def __init__(self, allowed_domains=[], start_urls=[], 
      rules=[], findtag='', finditemprop='', keywords='', **kwargs): 
     CrawlSpider.__init__(self, **kwargs) 
     self.allowed_domains = allowed_domains 
     self.start_urls = start_urls 
     self.rules = rules 
     self.findtag = findtag 
     self.finditemprop = finditemprop 
     self.keywords = keywords 

    def parse_item(self, response): 
     contentTags = [] 

     soup = BeautifulSoup(response.body) 

     contentTags = soup.findAll(self.findtag, itemprop=self.finditemprop) 

     for contentTag in contentTags: 
      matchedResult = re.search(self.keywords, contentTag.text) 
      if matchedResult: 
       print('URL Found: ' + response.url) 
2

Bạn có thể tạo ra một con nhện thời gian chạy được đánh giá bởi các thông dịch viên. mảnh Mã này có thể được đánh giá trong thời gian chạy như vậy:

a = open("test.py") 
from compiler import compile 
d = compile(a.read(), 'spider.py', 'exec') 
eval(d) 

MySpider 
<class '__main__.MySpider'> 
print MySpider.start_urls 
['http://www.somedomain.com'] 
2

tôi sử dụng cách tiếp cận Scrapy Extensions để mở rộng các lớp Spider để một lớp có tên Masterspider bao gồm một phân tích cú pháp chung chung.

Dưới đây là phiên bản "ngắn" rất ngắn của trình phân tích cú pháp mở rộng chung của tôi. Lưu ý rằng bạn cần triển khai trình kết xuất với công cụ Javascript (chẳng hạn như Selenium hoặc BeautifulSoup) ngay sau khi bạn bắt đầu làm việc trên các trang bằng AJAX. Và rất nhiều mã bổ sung để quản lý sự khác biệt giữa các trang web (phế liệu dựa trên tiêu đề cột, xử lý tương đối so với URL dài, quản lý các loại vùng chứa dữ liệu khác nhau, v.v ...).

Điều gì đang gây nhiễu với phương pháp Tiếp cận tiện ích mở rộng là bạn vẫn có thể ghi đè phương pháp phân tích cú pháp chung nếu có điều gì đó không phù hợp nhưng tôi chưa bao giờ phải làm như vậy. Lớp Masterspider kiểm tra xem một số phương thức đã được tạo ra chưa (ví dụ: parser_start, next_url_parser ...) trong lớp spider cụ thể của trang web để cho phép quản lý các đặc trưng: gửi biểu mẫu, xây dựng yêu cầu next_url từ các phần tử trong trang, v.v.

Khi tôi đang cạo các trang web khác nhau, luôn có các tính năng cụ thể để quản lý. Đó là lý do tại sao tôi muốn giữ một lớp cho mỗi trang web được cạo để tôi có thể viết một số phương pháp cụ thể để xử lý nó (trước/sau xử lý ngoại trừ PipeLines, Request generator ...).

masterspider/sitespider/settings.py

EXTENSIONS = { 
    'masterspider.masterspider.MasterSpider': 500 
} 

masterspider/masterspdier/masterspider.py

# -*- coding: utf8 -*- 
from scrapy.spider import Spider 
from scrapy.selector import Selector 
from scrapy.http import Request 
from sitespider.items import genspiderItem 

class MasterSpider(Spider): 

    def start_requests(self): 
     if hasattr(self,'parse_start'): # First page requiring a specific parser 
      fcallback = self.parse_start 
     else: 
      fcallback = self.parse 
     return [ Request(self.spd['start_url'], 
        callback=fcallback, 
        meta={'itemfields': {}}) ] 

    def parse(self, response): 
     sel = Selector(response) 
     lines = sel.xpath(self.spd['xlines']) 
     # ... 
     for line in lines: 
      item = genspiderItem(response.meta['itemfields'])    
      # ... 
      # Get request_url of detailed page and scrap basic item info 
      # ... 
      yield Request(request_url, 
        callback=self.parse_item, 
        meta={'item':item, 'itemfields':response.meta['itemfields']}) 

     for next_url in sel.xpath(self.spd['xnext_url']).extract(): 
      if hasattr(self,'next_url_parser'): # Need to process the next page URL before? 
       yield self.next_url_parser(next_url, response) 
      else: 
       yield Request(
        request_url, 
        callback=self.parse, 
        meta=response.meta) 

    def parse_item(self, response): 
     sel = Selector(response) 
     item = response.meta['item'] 
     for itemname, xitemname in self.spd['x_ondetailpage'].iteritems(): 
      item[itemname] = "\n".join(sel.xpath(xitemname).extract()) 
     return item 

masterspider/sitespider/nhện/somesite_spider.py

# -*- coding: utf8 -*- 
from scrapy.spider import Spider 
from scrapy.selector import Selector 
from scrapy.http import Request 
from sitespider.items import genspiderItem 
from masterspider.masterspider import MasterSpider 

class targetsiteSpider(MasterSpider): 
    name = "targetsite" 
    allowed_domains = ["www.targetsite.com"] 
    spd = { 
     'start_url' : "http://www.targetsite.com/startpage", # Start page 
     'xlines' : "//td[something...]", 
     'xnext_url' : "//a[contains(@href,'something?page=')]/@href", # Next pages 
     'x_ondetailpage' : { 
      "itemprop123" :  u"id('someid')//text()" 
      } 
    } 

#  def next_url_parser(self, next_url, response): # OPTIONAL next_url regexp pre-processor 
#   ... 
0

As far khi thu thập các tên miền cụ thể được truyền dưới dạng đối số, tôi chỉ ghi đè Spider.__init__:

class MySpider(scrapy.Spider): 
    """ 
    This spider will try to crawl whatever is passed in `start_urls` which 
    should be a comma-separated string of fully qualified URIs. 

    Example: start_urls=http://localhost,http://example.com 
    """ 
    def __init__(self, name=None, **kwargs): 
     if 'start_urls' in kwargs: 
      self.start_urls = kwargs.pop('start_urls').split(',') 
     super(Spider, self).__init__(name, **kwargs) 
Các vấn đề liên quan