2012-06-17 12 views
9

Tôi hiện đang làm việc trên một dự án scraper, điều quan trọng là đảm bảo mọi yêu cầu đã được xử lý đúng cách, tức là, hoặc để ghi lại lỗi hoặc lưu kết quả thành công. Tôi đã triển khai spider cơ bản và bây giờ tôi có thể xử lý 99% yêu cầu thành công, nhưng tôi có thể gặp lỗi như captcha, 50x, 30x hoặc thậm chí không có đủ trường trong kết quả (sau đó tôi sẽ thử một trang web khác để tìm các trường bị thiếu). Đầu tiên, tôi nghĩ rằng nó "hợp lý hơn" để tăng ngoại lệ trong việc gọi lại phân tích cú pháp và xử lý tất cả chúng trong errback, điều này có thể làm cho mã dễ đọc hơn. Quay lại đầu trang | Nhưng tôi đã cố gắng chỉ để tìm ra errback chỉ có thể bẫy lỗi trong mô-đun tải xuống, chẳng hạn như trạng thái phản hồi không 200. Nếu tôi nâng ParseError tự thực hiện trong cuộc gọi lại, con nhện chỉ tăng nó lên và dừng lại.làm thế nào để xử lý tất cả các loại ngoại lệ trong một dự án cồng kềnh, trong errback và gọi lại?

Ngay cả khi tôi sẽ phải xử lý yêu cầu phân tích trực tiếp trong cuộc gọi lại, tôi không biết cách thử lại yêu cầu ngay lập tức trong cuộc gọi lại theo cách sạch sẽ. bạn biết đấy, tôi có thể phải bao gồm một proxy khác để gửi yêu cầu khác hoặc sửa đổi một số tiêu đề yêu cầu.

Tôi thừa nhận mình khá mới mẻ nhưng tôi đã cố gắng qua lại trong nhiều ngày và vẫn không thể làm việc này ... Tôi đã kiểm tra mọi câu hỏi trên SO và không ai khớp, cảm ơn trước vì Cứu giúp.

UPDATE: Tôi nhận ra điều này có thể là một câu hỏi rất phức tạp vì vậy tôi cố gắng để minh họa kịch bản trong mã giả sau đây, hy vọng điều này sẽ giúp:

from scraper.myexceptions import * 

def parseRound1(self, response): 

    .... some parsing routines ... 
    if something wrong happened: 
     # this causes the spider raises a SpiderException and stops 
     raise CaptchaError 
    ... 

    if no enough fields scraped: 
     raise ParseError(task, "no enough fields") 
    else: 
     return items 

def parseRound2(self, response): 
    ...some other parsing routines... 

def errHandler(self, failure): 
    # how to trap all the exceptions? 
    r = failure.trap() 
    # cannot trap ParseError here 
    if r == CaptchaError: 
     # how to enqueue the original request here? 
     retry 
    elif r == ParseError: 
     if raised from parseRound1: 
      new request for Round2 
     else: 
      some other retry mechanism 
    elif r == HTTPError: 
     ignore or retry 

Trả lời

0

Lúc đầu, tôi nghĩ rằng nó là nhiều hơn "logic "để tăng ngoại lệ trong các cuộc gọi lại phân tích cú pháp và xử lý tất cả các lỗi này trong trường hợp sai, điều này có thể làm cho mã dễ đọc hơn. Nhưng tôi đã cố gắng chỉ để tìm hiểu sai lầm chỉ có thể bẫy các lỗi trong mô-đun trình tải xuống, chẳng hạn như trạng thái phản hồi không phải 200. Nếu Tôi nâng ParseError tự thực hiện trong cuộc gọi lại, con nhện chỉ tăng nó và dừng lại.

Vâng, bạn là đúng - callbackerrback có nghĩa là để được sử dụng chỉ với downloader, như twisted được sử dụng để tải về một tài nguyên, và xoắn sử dụng deffereds - đó là lý do tại sao callbacks là cần thiết.

Phần không đồng bộ duy nhất trong mẩu tin lưu niệm thường là trình tải xuống, tất cả các phần khác hoạt động đồng bộ.

Vì vậy, nếu bạn muốn bắt tất cả các lỗi không downloader - tự mình làm:

  • thực hiện một thử lớn/trừ trong callback
  • hoặc thực hiện một trang trí cho callbacks của bạn mà sẽ làm điều này (i thích ý tưởng này hơn)
+0

cảm ơn vì đã làm rõ trách nhiệm của 'callback' và' err back'! Điều này đã làm tôi bối rối trong một thời gian dài .. đoán tôi nên đã tìm ra nó bằng cách viết một số nhện kiểm tra trước đó ... –

8

EDIT 16 Tháng Mười một 2012: Scrapy> = 0.16 sử dụng một phương pháp khác nhau để đính kèm các phương pháp với các tín hiệu, thêm ví dụ thêm

giải pháp đơn giản nhất sẽ viết một phần mở rộng trong đó bạn chụp được các lỗi, sử dụng các tín hiệu Scrapy. Ví dụ; phần mở rộng sau sẽ bắt được tất cả các lỗi và in một dấu vết.

Bạn có thể làm bất kỳ điều gì với Lỗi - như lưu vào cơ sở dữ liệu của bạn hoặc gửi email - bản thân nó là một phiên bản twisted.python.failure.Failure.

Đối với phiên bản Scrapy đến 0.16:

from scrapy import signals 
from scrapy.xlib.pydispatch import dispatcher 

class FailLogger(object): 
    def __init__(self): 
    """ 
    Attach appropriate handlers to the signals 
    """ 
    dispatcher.connect(self.spider_error, signal=signals.spider_error) 

    def spider_error(self, failure, response, spider): 
    print "Error on {0}, traceback: {1}".format(response.url, failure.getTraceback()) 

Đối với phiên bản Scrapy từ 0.16 trở lên:

from scrapy import signals 

class FailLogger(object): 

    @classmethod 
    def from_crawler(cls, crawler): 
    ext = cls() 

    crawler.signals.connect(ext.spider_error, signal=signals.spider_error) 

    return ext 

    def spider_error(self, failure, response, spider): 
    print "Error on {0}, traceback: {1}".format(response.url, failure.getTraceback()) 

Bạn sẽ cho phép phần mở rộng trong các thiết lập, với một cái gì đó như:

EXTENSIONS = { 
'spiders.extensions.faillog.FailLogger': 599, 
} 
+0

Cảm ơn Sjaak, tôi chỉ cần nhìn vào tài liệu liên quan đến phần mở rộng nhiều hơn, âm thanh này phù hợp với yêu cầu của tôi! Tệ quá, tôi đã không hiểu rõ nó một tuần trước khi tôi bắt đầu lúng túng. Tôi sẽ cung cấp cho nó một shot sau, tôi đang nghĩ đến việc sử dụng một danh sách redis cho lịch trình. –

+0

Không chắc chắn nếu điều này cần một câu hỏi khác, nhưng bạn có thể giải thích những sửa đổi cần phải được thực hiện để kết hợp các lớp 'FailLogger' vào phần còn lại của phế liệu? Tôi đã sửa đổi 'EXTENSIONS' trong' settings.py' và thêm 'faillog.py' vào thư mục' extensions'. Kết quả đầu ra lậu '2016-01-29 16:24:07 [scrapy] INFO: Tiện ích mở rộng đã bật: FailLogger', vì vậy tôi nghĩ việc triển khai của tôi là ok. Tôi đang thử nghiệm trên [liên kết này] (https://www.release.tdnet.info/inbs/140120160122493328.pdf), trả về một 'DNSLookupError', nhưng câu lệnh in trong lớp' FailLogger' không được trả về. .. – JSB

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