3

URL を含むメッセージを受け入れるシステムがあります。特定のキーワードがメッセージに含まれている場合、URL をパラメーターとして使用して API 呼び出しが行われます。

処理を節約し、最終的なプレゼンテーションを効率的に保つために。

特定の時間範囲内に重複した URL が送信されるのは望ましくありません。

したがって、この URL ---> http://instagram.com/p/gHVMxltq_8/が入ってきて、API に送信された場合

          url = incoming.msg['urls']
          url = urlparse(url)
          if url.netloc  == "instagram.com":                
            r = requests.get("http://api.some.url/show?url=%s"% url)

それから 3 秒後に同じ URL が入ってきますが、それを API に送信したくありません。

重複したメッセージが時間に基づいて API に送信されるのを排除/制限するには、どのプログラミング方法を展開すればよいですか?

TIM PETERS メソッドを使用した更新:

         limit = DecayingSet(86400)
         l = limit.add(longUrl)
         if l == False:
           pass
         else:
           r = requests.get("http://api.some.url/show?url=%s"% url)

このスニペットは、tcp 経由でストリーミング メッセージを受け入れる長時間実行されるプロセス内にあります。

同じ URL を渡すたびに、l は毎回 True を返します。

しかし、インタープリターで試してみると、すべて問題なく、設定時間が経過していない場合は False が返されます。

セットが追加されている間、スクリプトが実行されているという事実と関係がありますか?

インスタンスの問題?

4

3 に答える 3

4

やり過ぎかもしれませんが、私はこの種の新しいクラスを作成するのが好きです。要件がいつ複雑になるかはわかりません ;-) たとえば、

from time import time

class DecayingSet:
    def __init__(self, timeout): # timeout in seconds
        from collections import deque
        self.timeout = timeout
        self.d = deque()
        self.present = set()

    def add(self, thing):
        # Return True if `thing` not already in set,
        # else return False.
        result = thing not in self.present
        if result:
            self.present.add(thing)
            self.d.append((time(), thing))
        self.clean()
        return result

    def clean(self):
        # forget stuff added >= `timeout` seconds ago
        now = time()
        d = self.d
        while d and now - d[0][0] >= self.timeout:
            _, thing = d.popleft()
            self.present.remove(thing)

書かれているように、新しいものを追加しようとするたびに有効期限をチェックします。dequeたぶんそれはあなたが望むものではないかもしれませんが、アイテムが追加された順に保持されるので、それは安価なチェックであるはずです。たくさんの可能性。

なぜdequeですか?アイテムの数が自明でなくなった場合よりもはるかに高速だからdeque.popleft()です。list.pop(0)

于 2013-10-31T02:45:48.353 に答える
1

希望する間隔が 1 時間であると仮定し、1 時間ごとに増分する 2 つのカウンターを保持しますが、それらは互いに 30 分ずれています。つまり、カウンター A は1, 2, 3, 4に進み、11:17, 12:17, 13:17, 14:17カウンター B は1, 2, 3, 4になり11:47, 12:47, 13:47, 14:47ます。

リンクが入ってきて、以前のリンクと同じ 2 つのカウンターのいずれかを持つ場合、それは重複していると見なします。

明示的なタイムスタンプに対するこのスキームの利点は、url+counterA と url+counterB をハッシュして、url が存在するかどうかをすばやく確認できることです。

更新: 2 つのデータ ストアが必要です。1 つは列を含む通常のデータベース テーブル (低速) で、もう 1 つ(url, counterA, counterB)nビット単位のメモリ (高速) です。url so.com、 counterA 17、 counterBが与えられた場合18、最初に "17,so.com" を範囲内0にハッシュn - 1し、そのアドレスのビットがオンになっているかどうかを確認します。同様に、「18,so.com」をハッシュして、ビットがオンになっているかどうかを確認します。

いずれの場合もビットがオンになっていない場合は、1 時間以内にそれが新しい URL であると確信しているため、(迅速に) 完了します。

どちらの場合もビットがオンになっている場合は、データベース テーブルで URL を調べて、実際にその URL であるか、同じビットにハッシュされた他の URL であるかを確認します。

さらに更新:ブルーム フィルターは、このスキームの拡張です。

于 2013-10-31T02:24:59.897 に答える
0

最近使用した URL のメモリ内キャッシュを保持することをお勧めします。辞書のようなもの:

urls = {}

次に、各 URL について:

if url in urls and (time.time() - urls[url]) < SOME_TIMEOUT:
    # Don't submit the data
else:
    urls[url] = time.time()
    # Submit the data
于 2013-10-31T02:25:29.840 に答える