42

CrawlSpiderでscrapyを使用してWebサイトのクローラーを作成しています。

Scrapyは、URLに基​​づいて重複リクエストをフィルタリングする組み込みの重複リクエストフィルターを提供します。また、CrawlSpiderのルールメンバーを使用してリクエストをフィルタリングできます。

私がやりたいのは、次のようなリクエストをフィルタリングすることです。

http:://www.abc.com/p/xyz.html?id=1234&refer=5678

すでに訪問したことがある場合

http:://www.abc.com/p/xyz.html?id=1234&refer=4567

注: referは、取得する応答に影響を与えないパラメーターであるため、そのパラメーターの値が変更されてもかまいません。

これで、すべてのIDを累積するセットがある場合、この機能を実現するために、コールバック関数parse_item(これが私のコールバック関数)でそれを無視できます。

しかし、それは、必要のないときに、少なくともそのページをフェッチしていることを意味します。

では、URLに基​​づいて特定のリクエストを送信するべきではないことをscrapyに伝える方法は何ですか?

4

5 に答える 5

41

重複を削除するカスタムミドルウェアを作成して、設定に追加できます

import os

from scrapy.dupefilter import RFPDupeFilter

class CustomFilter(RFPDupeFilter):
"""A dupe filter that considers specific ids in the url"""

    def __getid(self, url):
        mm = url.split("&refer")[0] #or something like that
        return mm

    def request_seen(self, request):
        fp = self.__getid(request.url)
        if fp in self.fingerprints:
            return True
        self.fingerprints.add(fp)
        if self.file:
            self.file.write(fp + os.linesep)

次に、settings.pyで正しいDUPFILTER_CLASSを設定する必要があります

DUPEFILTER_CLASS = 'scraper.duplicate_filter.CustomFilter'

その後は動作するはずです

于 2012-11-28T13:15:35.627 に答える
10

ytomarの指導に従い、メモリ内のセットをチェックすることですでに表示されているURLのみに基づいてフィルタリングするこのフィルターを作成しました。私はPythonの初心者なので、何かを台無しにした場合は知らせてください。ただし、問題なく動作しているようです。

from scrapy.dupefilter import RFPDupeFilter

class SeenURLFilter(RFPDupeFilter):
    """A dupe filter that considers the URL"""

    def __init__(self, path=None):
        self.urls_seen = set()
        RFPDupeFilter.__init__(self, path)

    def request_seen(self, request):
        if request.url in self.urls_seen:
            return True
        else:
            self.urls_seen.add(request.url)

ytomarが述べたように、必ずDUPEFILTER_CLASS定数をsettings.py:に追加してください。

DUPEFILTER_CLASS = 'scraper.custom_filters.SeenURLFilter'
于 2013-09-15T04:56:43.693 に答える
3

https://github.com/scrapinghub/scrapylib/blob/master/scrapylib/deltafetch.py

このファイルはあなたを助けるかもしれません。このファイルは、URLから一意のデルタフェッチキーのデータベースを作成します。ユーザーはscrapy.Reqeust(meta = {'deltafetch_key':uniqe_url_key})を渡します。これにより、過去にアクセスしたことのある重複したリクエストを回避できます。

deltafetch.py​​を使用したmongodb実装のサンプル

        if isinstance(r, Request):
            key = self._get_key(r)
            key = key+spider.name

            if self.db['your_collection_to_store_deltafetch_key'].find_one({"_id":key}):
                spider.log("Ignoring already visited: %s" % r, level=log.INFO)
                continue
        elif isinstance(r, BaseItem):

            key = self._get_key(response.request)
            key = key+spider.name
            try:
                self.db['your_collection_to_store_deltafetch_key'].insert({"_id":key,"time":datetime.now()})
            except:
                spider.log("Ignoring already visited: %s" % key, level=log.ERROR)
        yield r

例えば。id = 345 sparky.Request(url、meta = {deltafetch_key:345}、callback = parse)

于 2015-02-19T12:45:35.723 に答える
1

これが、scrapy0.24.6のカスタムフィルターベースです。

このフィルターでは、URLのIDのみを考慮します。例えば

http://www.example.com/products/cat1/1000.html?p=1 http://www.example.com/products/cat2/1000.html?p=2

同じURLとして扱われます。だが

http://www.example.com/products/cat2/all.html

しない。

import re
import os
from scrapy.dupefilter import RFPDupeFilter


class MyCustomURLFilter(RFPDupeFilter):

    def _get_id(self, url):
        m = re.search(r'(\d+)\.html', url)
        return None if m is None else m.group(1)

    def request_fingerprint(self, request):
        style_id = self._get_id(request.url)
        return style_id
于 2015-05-29T23:58:36.543 に答える
0

最新のscrapyでは、デフォルトの複製フィルターを使用するか、拡張してカスタムフィルターを使用できます。

スパイダー設定で以下の構成を定義します

DUPEFILTER_CLASS = 'scrapy.dupefilters.BaseDupeFilter'

于 2020-01-28T13:59:13.507 に答える