スピード?
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)のインデックスを作成しないように、関数コードですべてを非常に簡単に変更できます。
ヨイハジ
ハブルからの眺め