2

何百万ものドメインのリストから 1 ~ 3 ページを取得する Web クローラーを構築しています。マルチスレッドで Python を使用しています。束) とツイスト、スクレイピーですが、どれも約 10 メガビット以上の帯域幅を使用することを許可していません (私は 60 メガビットの速度を持っています)。通常、約 100-300 スレッドで最大になり、その後、失敗した要求が発生します。 . php/curlでもこの問題が発生しました。urllib3 と Threads モジュール (Python) を使用して google plus ページからスクレイピングし、100mbit 接続を最大化するスクレーパーを持っています (これは、同じホストで開いているソケットを再利用しており、google が高速であるためと考えられます)。ネットワーク応答)

これは、pycurl を使用したスクリプトの 1 つの例です。URL を含む csv ファイルから URL を読み取っています。

import pycurl
from threading import Thread
from Queue import Queue
import cStringIO


def get(readq,writeq):
    buf = cStringIO.StringIO()
    while True:
        url=readq.get()

        c = pycurl.Curl()
        c.setopt(pycurl.TIMEOUT, 15)
        c.setopt(pycurl.FOLLOWLOCATION, 1)
        c.setopt(pycurl.USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:24.0) Gecko/20100101 Firefox/24.0')
        c.setopt(c.WRITEFUNCTION, buf.write)
        c.setopt(c.URL, url)
        try:
            c.perform()
            writeq.put(url+'  '+str(c.getinfo(pycurl.HTTP_CODE)))
        except:
            writeq.put('error  '+url)
print('hi')
readq=Queue()
writeq=Queue()

import csv
reader=csv.reader(open('alldataunq2.csv'))
sites = []
ct=0
for l in reader:
    if l[3] != '':
        readq.put('http://'+l[3])
        ct+=1
        if ct > 100000:
            break

t=[]
for i in range(100):
    Thread(target=get,args=(readq,writeq)).start()

while True:
    print(writeq.get())

私のプロセッサ/メモリはほとんど使用されていないため、ボトルネックは間違いなくネットワーク IO です。100 メガビット以上のフル接続を使用できる同様のスクレーパーの作成に成功した人はいますか?

スクレイピングコードの速度を上げる方法についての意見は大歓迎です

4

3 に答える 3

3

クロール速度を最適化する際に留意する必要がある要因がいくつかあります。

接続局所性

接続を効果的に再利用するには、同じ Web サイトの接続を再利用していることを確認する必要があります。以前のホストに 2 回ヒットするまでに時間がかかりすぎると、接続がタイムアウトする可能性があり、それは良くありません。新しいソケットを開くのは比較的コストのかかる操作なので、絶対に避けたいものです。これを達成する単純なヒューリスティックは、ダウンロード ターゲットをホストごとに並べ替え、一度に 1 つのホストをダウンロードすることですが、次の問題に遭遇します...

ホスト間の負荷分散

すべてのホストがファット パイプを備えているわけではないため、複数のホストを同時にヒットすることをお勧めします。これは、1 つのホストへの過剰なスパムを回避するのにも役立ちます。ここでの適切な戦略は、複数のワーカーを用意し、各ワーカーが一度に 1 つのホストに集中するようにすることです。このようにして、各ワーカーのコンテキスト内でホストごとのダウンロード速度を制御でき、各ワーカーは独自の接続プールを維持して接続を再利用します。

ワーカーの専門化

スループットを台無しにする 1 つの方法は、データ処理ルーチン (HTML の解析、リンクの抽出など) とフェッチ ルーチンを混在させることです。ここでの良い戦略は、取得ワーカーで最小限の処理作業を行い、別のワーカー セットが後で取得して処理できるようにデータを保存することです (場合によっては別のマシンでも)。

これらのことを念頭に置いておくと、接続からさらに絞り込むことができるはずです. いくつかの無関係な提案: の使用を検討してwgetください。簡単なクロールを実行するのにどれほど効果的であるかに驚かれることでしょう (巨大なマニフェスト ファイルから読み取ることもできます)。

于 2013-11-03T23:23:45.137 に答える
1

Webスクレイピングを行っているときに、インターネット接続の最大スループットに近づくことは期待できないと思います.

スクレイピング (および一般的な Web ブラウジング) には、多くの小さな要求が含まれます。その時間のかなりの部分は、接続のセットアップと切断、およびリモート エンドでのコンテンツの配信開始の待機に費やされます。積極的にコンテンツをダウンロードするのに費やされた時間は、おそらく 50% 前後だと思います。大量の大きなファイルをダウンロードしている場合は、平均スループットが向上すると思います。

于 2013-11-03T20:33:21.690 に答える
0

Scrapy-redis でスクレイピーを試してください。

、およびの設定を調整する必要があります。また、 と があることを確認してください。CONCURRENT_REQUESTSCONCURRENT_REQUESTS_PER_DOMAINCONCURRENT_REQUESTS_PER_IPDOWNLOAD_DELAY = 0AUTOTHROTTLE_ENABLED = False

于 2013-11-04T13:13:31.953 に答える