4

検索結果ページをクロールして、同じページからタイトルとリンク情報をスクレイピングしています。検索ページとして、SgmlLinkExtractor で許可するように指定した次のページへのリンクもあります。

問題の説明は、最初のページで、クロールするページ2とページ3のリンクを見つけましたが、完全にクロールされます。しかし、2 ページ目をクロールすると、再び Page1 (前のページ) と Page3 (次のページ) へのリンクが表示されます。そのため、リファラーを Page2 として Page1 を再度クロールし、ループに入ります。

私が使っているスクレイピーのバージョンは0.17です。

私は答えをウェブで検索し、次のことを試しました.1)

Rule(SgmlLinkExtractor(allow=("ref=sr_pg_*")), callback="parse_items_1", unique= True, follow= True),

しかし、固有のコマンドは有効なパラメーターとして識別されませんでした。

2) 設定でデフォルトのフィルタを DUPEILTER_CLASS = RFPDupeFilter として指定しようとしました

    DUPEFILTER_CLASS = RFPDupeFilter
NameError: name 'RFPDupeFilter' is not defined

3) Web でスニペットを見つけたカスタム フィルターも使用しようとしましたが、あまり理解できません。コードは次のとおりです。訪問 ID とステータスは取得されますが、既にクロールされたページは識別されません。

注: スニペットは Web からコピーされたもので、詳細はわかりません。

from scrapy import log
from scrapy.http import Request
from scrapy.item import BaseItem
from scrapy.utils.request import request_fingerprint
from Amaze.items import AmazeItem

class IgnoreVisitedItems(object):
    FILTER_VISITED = 'filter_visited'
    VISITED_ID = 'visited_id'
    CONTEXT_KEY = 'visited_ids'

    def process_spider_output(self, response, result, spider):
        context = getattr(spider, 'context', {})
        visited_ids = context.setdefault(self.CONTEXT_KEY, {})
        ret = []
        for x in result:
            visited = False
            if isinstance(x, Request):
                if self.FILTER_VISITED in x.meta:
                    visit_id = self._visited_id(x)
                    if visit_id in visited_ids:
                        log.msg("Ignoring already visited: %s" % x.url,
                                level=log.INFO, spider=spider)
                        visited = True
            elif isinstance(x, BaseItem):
                visit_id = self._visited_id(response.request)
                if visit_id:
                    visited_ids[visit_id] = True
                    x['visit_id'] = visit_id
                    x['visit_status'] = 'new'
            if visited:
                ret.append(MyItem(visit_id=visit_id, visit_status='old'))
            else:
                ret.append(x)
        return ret

    def _visited_id(self, request):
        return request.meta.get(self.VISITED_ID) or request_fingerprint(request)

私の意図は、クロールされたページをリストに入れ、ページがクロールされるかリストにないたびに一致するのではなく、スパイダー自体が既にクロールされた Web ページを無視するようにすることです。

これについて何か考えてください。

4

1 に答える 1

1

Spider のコード例は示されていませんが、メソッドdont_filter = Trueを呼び出すときに引数を渡すことは可能ですRequest。明示的に指定してみてくださいRequest(dont_filter=False)。これは、Spider が同じ要求を繰り返す必要がないことを示しています。

于 2013-03-27T12:24:35.427 に答える