ホームページ >バックエンド開発 >Python チュートリアル >Python を使用してクローラーを作成する方法
「
始めましょう」は良い動機ではありますが、時間がかかる可能性があります。手中または頭の中にプロジェクトがある場合、実際には目標に突き動かされ、学習モジュールのようにゆっくりと学習することはありません。
さらに、知識について話す場合、システム内の各知識ポイントがグラフ内の点であり、依存関係がエッジである場合、グラフは有向非巡回グラフであってはなりません。なぜなら、A の学習経験は B の学習に役立つからです。したがって、「始め方」を学ぶ必要はありません。そのような「始め方」のポイントは存在しないからです。もちろん、学習する必要があります。最初に Python を知る必要があるということです。そうでない場合、どうやって Python を学習してクローラーを作成できるのでしょうか。しかし、実際には、このクローラーを作成する過程で Python を学習できます。
以前の多くの回答で言及されている「テクニック」を見ました - ソフトウェアはどのようにクロールするのですか? 「タオ」と「テクノロジー」について話しましょう - クローラーがどのように機能するのか、そしてそれを Python で実装する方法
簡単に要約します:
クローラーの基本的な動作原理を学ぶ必要があります
基本的な HTTP スクレイピング ツール、scrapy
ブルーム フィルター: サンプルによるブルーム フィルター
大規模な Web ページをクロールする必要がある場合実際、分散クローラーの概念を学ぶ必要があります。実際、最も単純な実装は python-rq (https://github.com/nvie) です。 /rq
rq と Scrapy の組み合わせ: darkrho/scrapy-redis · GitHub
フォローアップ処理、Web ページ Disjunction (grangier/python-goose · GitHub)、ストレージ (Mongodb)
以下は短いですストーリー:
クラスターを作成したときに Douban 全体を降りた経験について教えてください
1) まず、クローラーがどのように機能するかを理解する必要があります
あなたがクモになったと想像してください。インターネットです。それでは、どうすればよいでしょうか。たとえば、人民日報のトップページをクリックするだけです。これは、トップページの
で表されます。人民日報のページへのさまざまなリンクが表示されるので、「国内」ページから喜んでアクセスしました。これで、2 ページ (ホームページと国内ニュース) のクロールが完了しました。クロールダウンしたページの対処方法について、このページを HTML に完全にコピーしたと想像してください
突然、国内のニュース ページに「ホームページ」へのリンクがあることに気づきました。賢いスパイダーとして、すでに見ているので、戻ってくる必要がないことを知っておく必要があります。つまり、閲覧したページのアドレスを保存する必要があります。このようにして、クロールする必要がある可能性のある新しいリンクを見つけるたびに、まず頭の中でこのページ アドレスに既にアクセスしたかどうかを確認します。そこに行ったことがあるなら、行かないでください。
理論的には、最初のページからすべてのページに到達できれば、すべての Web ページを確実にクロールできることが証明できます。
では、それをPythonで実装するにはどうすればよいでしょうか?
非常に簡単です
import Queueinitial_page = "http://www.renminribao.com"url_queue = Queue.Queue()seen = set()seen.insert(initial_page)url_queue.put(initial_page)while(True):
#すべてが終了するまで続行します
if url_queue.size()>0:
current_url = url_queue.get() #キュー内の最初の URL を取得します
store(current_url) #この URL で表される Web ページを保存します _ For extract_urls の next_url (Current_url): #
URL
IF NEXT_URL NORL NORL NORL NORL NORL NORL NORL NORL NORL それ以外の場合: Break
はすでに非常に適切な擬似コードです。
すべてのクローラーのバックボーンはここにあります。クローラーが実際には非常に複雑である理由を分析してみましょう。通常、検索エンジン会社は、クローラーを保守および開発するためにチーム全体を抱えています。
2) 効率
上記のコードを直接処理して実行すると、Douban のコンテンツ全体をクロールするのに 1 年かかります。 Google のような検索エンジンはウェブ全体をクロールする必要があることは言うまでもありません。
何が問題ですか?クロールする必要がある Web ページが多すぎるため、上記のコードは遅すぎます。ネットワーク全体に N 個の Web サイトがあると仮定すると、再利用の判断の複雑さは N*log(N) であると分析します。これは、すべての Web ページを 1 回横断する必要があり、セットを毎回再利用するには log(N) の複雑さが必要になるためです。 OK、OK、Python の set 実装がハッシュであることはわかっていますが、これでもまだ遅すぎます。少なくともメモリ使用量は効率的ではありません。
体重を判断する通常の方法は何ですか?ブルーム フィルター。簡単に言うと、やはりハッシュ法ですが、その特徴は、固定メモリ (URL の数に応じて増加しない) を使用して、URL がすでにセットに含まれているかどうかを O(1) の効率で判断できることです。残念ながら、無料のランチなどというものは存在しません。唯一の問題は、URL がセットに含まれていない場合、BF はその URL が閲覧されていないと 100% 確信できることです。ただし、この URL がセットに含まれている場合は、「この URL はすでに表示されているはずですが、2% の不確実性があります」と表示されます。割り当てるメモリが十分大きい場合、ここでの不確実性は非常に小さくなる可能性があることに注意してください。簡単なチュートリアル: 例によるブルーム フィルター
この機能に注目してください。URL が一度閲覧されている場合、低い確率で繰り返し閲覧される可能性があります (何度閲覧しても疲れることはありません)。ただし、まだ閲覧されていない場合は、必ず閲覧されます (これは非常に重要です。そうしないと、一部の Web ページを見逃してしまいます!)。 [重要: この段落には問題があります。今は読み飛ばしてください]
さて、これで重量判定に対処する最速の方法に近づきました。もう 1 つのボトルネックは、マシンが 1 台しかないことです。帯域幅がどれほど大きくても、マシンが Web ページをダウンロードする速度がボトルネックである限り、この速度を上げることしかできません。 1 台のマシンでは不十分な場合は、多数のマシンを使用してください。もちろん、マルチスレッド (Python の場合はマルチプロセス) を使用して、各マシンが最大の効率に達していることを前提としています。
3) クラスターのクローリング
Douban をクローリングするとき、合計 100 台以上のマシンを使用して 1 か月間 24 時間稼働させました。 1 台のマシンしか使用しない場合、それを 100 か月間実行する必要があることを想像してください...
それでは、現在 100 台のマシンが利用できると仮定して、Python を使用して分散クローリング アルゴリズムを実装するにはどうすればよいでしょうか?
100 台のマシンのうち 99 台の計算能力が小さいマシンをスレーブと呼び、他の大きなマシンをマスターと呼びます。次に、上記のコードの url_queue を見て、このキューをこのマスターに配置できれば、マシン上ではすべてのスレーブが配置されます。スレーブは、Web ページのダウンロードを完了するたびに、マスターにクロールする新しい Web ページを要求します。スレーブは新しい Web ページをキャプチャするたびに、この Web ページ上のすべてのリンクをマスターのキューに送信します。同様に、ブルーム フィルターもマスターに配置されますが、マスターはアクセスされていない URL のみをスレーブに送信します。ブルーム フィルターはマスターのメモリに配置され、訪問先 URL はマスター上で実行されている Redis に配置されるため、すべての操作が O(1) であることが保証されます。 (少なくとも償却額は O(1) です。Redis のアクセス効率については、LINSERT – Redis を参照してください)
Python で実装する方法を検討してください:
各スレーブにscrapyをインストールすると、各マシンが有能なマシンになります対応するスレーブを取得し、マスターに Redis と rq をインストールして分散キューとして使用します。
コードは次のように書かれています
#slave.py current_url = request_from_master() to_send = [] for next_url in extract_urls(current_url): to_send.append(next_url) store(current_url); send_to_master(to_send) #master.py distributed_queue = DistributedQueue() bf = BloomFilter() initial_pages = "www.renmingribao.com" while(True): if request == 'GET': if distributed_queue.size()>0: send(distributed_queue.get()) else: break elif request == 'POST': bf.put(request.url)
上記とはいえ「 シンプル」を多用していますが、実際に商用規模のクローラを実装するのは簡単ではありません。上記のコードを使用すると、大きな問題なく Web サイト全体をクロールできます。
ただし、
有効なストレージ (データベースの配置方法)
効果的な情報抽出 (Web ページ「朝陽区中華路、フェンジン路」のすべての住所を抽出する方法など)。検索エンジンは通常、写真を保存する必要があるなど、すべての情報を保存する必要はありません。 ..
タイムリーな更新 (このページが更新される頻度を予測します)