multi_get-サイトの一括ダウンロード

このトピックは、インターネットサイトを最高速度でインデックス化したい人にとって興味深いものです(自家製の検索エンジン、単語頻度分析、html分析サービスなど)。ここでのスレッド化は最高速度、urllibを提供しません-特に... libcurlからの非同期リクエスト。



スピード?

500MHZ( 非常に、非常に弱いVPS)-1 秒あたり100 URL (100接続、2プロセス)。

Amazon EC2の「ハイCPUミディアムインスタンス」(0.2ドル/時間)〜1 秒あたり1200 URL (300接続、5つの同時プロセス)。 1つのプロセスで、1秒あたり最大660のURL。



多くのサイトをポンプアウトし、さらに処理するために、便利な関数の1つであるmulti_getを共有します。実際、CurlMultiの例から変更されたCurlMulti(libcurl)の便利なラッパーです。



>>> urls = ['http://google.com/', 'http://statcounter.com/']

>>> res = {}

>>> multi_get (res, urls, num_conn = 30, timeout = 5, percentile = 95)

>>> res['http://google.com/']

'<html><title>Google....

# res, HTML URL'








このコードは、30の接続を持つ2つのサイトをダウンロードします。 より正確には、もちろん、2つの接続で、しかしここに10,000個のURLを入力するのに十分なスペースがありませんでした。



グッズと有用性:



0. num_conn = 1の場合、関数はシリアル(パラレルではない)ダウンロードに変わりますが、以下のすべての利点(Cookie、ユーザーエージェント、無条件のタイムアウト)があります



1. resで想定する場合、「http://google.com/」を何らかの意味を持つものとして事前に定義します-このアドレスはダウンロードされません(スキップされます)。 一番下の行は、resが通常の辞書ではなく、何らかの形で永続的である場合(たとえば、ファイルまたは何らかのSQLに格納されている場合)、すべての呼び出しで以前にダウンロードされていないサイトのみがダウンロードされることです。



2. multi_get(res、url、 debug = 1 )-ダウンロードの進行状況に関する情報を表示します(コンソールはプロセスの速度を低下させるので、実稼働環境で無効にした方が良いです)。



3. multi_get(res、url、 percentile = 95 )-多くの場合、大きなリストのサイトの90〜99%がそれぞれほぼマイクロ秒でダウンロードされますが、大きなリストの1-2サイトは非常に遅くなります。 その結果、たとえば1分間に9,990個のサイトが飛行し、さらに10分間待ってさらに1分間待つと、効果が著しく低下します。したがって、このようなパラメーターがあります-95%(またはいくつ-99、50、75)の最速URLをダウンロードして終了します遅いものを期待することなく。



4. multi_get(res、url、 timeout = 5 )-別のURLへのタイムアウト-5秒(Pythonの組み込みソケットのタイムアウトとは異なり-常に機能し、理由もなくハングしません)。



5. ... ua = 'Mozilla / 5.0(互換性; Googlebot / 2.1; + http://www.google.com/bot.html)' ...-だから私たちは信じたが、まだ-どのユーザーエージェントを転送するか。



6. ... ref = 'http://google.com/bot.html' ...-リファラーを渡す

... ref_dict = {'http://google.com/': 'http://mysite.com/?url-google.com'}-リファラーが渡すURLへの値の辞書



7. ... cf = 'cookiefile.txt' ...- Cookieを使用して、このファイルに保存します。



8. ... follow = 0 ...-リダイレクトに従いません(デフォルトではフォローします)。

たとえば、すべての.comドメインのインデックスを作成すると、それらの多くが同じものにリダイレクトされるため、リダイレクトを単に無視する方が適切です。



9. res-必ずしも辞書ではありません。たとえば、def __setitem __(self、url、html)を実行する新しいMyDictクラスを定義できます。また、ダウンロード時にHTMLを非同期で処理します。 self):return []-空のリストまたはダウンロードする必要のないURLのリストを返します。



コード



残念ながら、Habrは空白(インデント)を削除します。これがないと、Pythonコードは機能しません。そのため、コードは次のとおりです: rarestblog.com/py/multi_get.py.txt (またはrarest.s3.amazonaws.com/multi_get.py.txt



10個のYQLクエリを作成して1000個のランダムリンクを取得し、それらの80%をダウンロードして速度を測定するコードの例があります。



重要な瞬間



pycurlをインストールする必要があります( pycurl.sourceforge.net/download

> easy_install pycurl





easy_installがインストールされていない場合、最初に:

> python -murllib http://peak.telecommunity.com/dist/ez_setup.py | python - -U setuptools



python -murllib http://peak.telecommunity.com/dist/ez_setup.py | python - -U setuptools





そして上の行。



テストスクリプトにはまだ必要です

> easy_install cjson





(オプションでcjson.decodeをsimplejson.loadsに置き換えることができます-理由がわかっている場合)



Linux / FreeBSDでc-aresをインストールする


Windowsでは、すべてがすでに順番に並んでいます(.exeセットアップファイルには「c-ares」のコンパイル済みサポートがすでに含まれています)が、サーバー(Linux / FreeBSD)には「c-ares」(非同期DNSクエリ)のサポートをインストールする必要があります。 pycurl / multi_getは10回クラッシュします-c-areなしでは20-30を超える接続を使用できません。



# wget http://curl.haxx.se/download/curl- 7.19.4 .tar.gz

# tar zxvf curl-7.19.4.tar.gz

# cd curl-7.19.4

Linux: # ./configure --enable-ares --with-ssl --enable-ipv6 --with-libidn

FreeBSD: # ./configure --enable-ares=/usr/local --with-ssl --enable-ipv6 --with-libidn



"--with-ssl --enable-ipv6 --with-libidn" - .



# make

# make install



[linux only]

:

# rm -rf /usr/lib/libcu*

# ln -s /usr/local/lib/libcurl.so.4 /usr/lib/libcurl.so.4

# ln -s /usr/local/lib/libcurl.so.4 /usr/lib/libcurl.so

# ldconfig

[ linux only]



# cd ..

# rm -rf curl-7*



# python -c "import pycurl;print pycurl.version"

, c-ares









アンチドス


2.スクリプトはかなりバカですが強力です-これを回避する簡単な方法でDOSのサイトを誤って起動する可能性があります-リストを圧縮して1つのドメインからURLが1つだけになるように小さなreduce_by_domain関数が含まれています誰かのサイトを置きます。



short_list_of_urls = reduce_by_domain(urls)







サイトを殺さずにすべてのURLをダウンロードする方法は? reduce_by_domain、multi_getを連続して数回呼び出します-resがクリアされない場合、同じURLが2回振り回されないことを覚えておいてください(「Goodies and Utilities」の1.を参照)。再度short_list_of_urlsを行う= reduce_by_domain(urls); multi_get(res、short_list_of_urls)。



その他のニュアンス:



無効なURLは、値"---"



で返されます。

100,000バイトを超えるファイルはダウンロードされません。

.Pdfファイルはダウンロードされません。



これは予防策として行われます。不要なもの(画像、.pdf)のインデックスを作成しないように、関数コードですべてを非常に簡単に変更できます。





ヨイハジ

ハブルからの眺め



All Articles