ホームページ  >  記事  >  バックエンド開発  >  Python を使用してマルチスレッド クローラーを作成し、Baidu Tieba の電子メール アドレスと携帯電話番号を取得する

Python を使用してマルチスレッド クローラーを作成し、Baidu Tieba の電子メール アドレスと携帯電話番号を取得する

巴扎黑
巴扎黑オリジナル
2017-03-18 10:48:221494ブラウズ

みんなが旧正月をどのように過ごすかはわかりませんが、コラムの所有者は 1 日家で寝ていましたが、目が覚めると QQ にログインし、誰かが私にソースコードのコピーを求めてきたことに気付きました。 Tieba クローラー。練習中に Baidu をクロールするコードを書いたことを思い出しました。Tieba 投稿レコードのメール アドレスと携帯電話番号のクローラーはオープンソースであり、誰もが学習して参照できるように共有されています。

要件分析:

このクローラーは主に Baidu Tieba のさまざまな投稿の内容をクロールし、投稿の内容を分析して携帯電話番号と電子メール アドレスを抽出します。主なフローはコードのコメントで詳しく説明されています。

テスト環境:

コードは Windows7 64 ビット、Python 2.7 64 ビット (mysqldb 拡張機能がインストールされている) および centos 6.5、Python 2.7 (mysqldb 拡張機能がインストールされている) 環境でテストされました。

働いています願望 スクリーンショットからわかるように、私の環境は Windows 7 + PyCharm です。私のPython環境はPython 2.7 64bitです。初心者向けの開発環境です。次に、easy_install をインストールすることをお勧めします。名前からわかるように、これは一部の拡張パッケージをインストールするために使用されます。たとえば、Python で mysql データベースを操作したい場合、Python はそれをネイティブにサポートしません。 Python が mysql データベースを操作できるようにするには、mysqldb パッケージをインストールする必要があります。easy_install がある場合は、mysqldb 拡張パッケージを 1 行で簡単にインストールできます。 -Ubuntuを入れると便利です。

関連するツールは私の github: cw1997/python-tools にあります。 easy_install をインストールするには、Python コマンド ラインで py スクリプトを実行するだけで、Windows 環境変数が自動的に追加されます。 Windows のコマンド ラインで easy_install と入力すると、エコーが表示され、インストールは成功します。

環境選択の詳細:

コンピューターハードウェアに関しては、もちろん速いほど良いため、少なくとも8Gのメモリから始めてください。これは、クローラー自体、特にマルチスレッドクローラーの場合、大量の中間データを保存および解析する必要があるためです。 、ページング リストと詳細ページを使用してクロールする場合、およびクロールされるデータの量が多い場合、キューを使用してクロール タスクを割り当てると多くのメモリが占​​有されます。キャプチャしたデータが json を使用している場合もあり、それが mongodb などの nosql データベースに保存されている場合、大量のメモリも消費します。

一部の劣悪な無線ルーターや市販の一般的な民間無線ネットワークカードでは、スレッドが比較的大きく開かれると断続的なネットワーク切断、データ損失、パケットドロップなどが発生するため、ネットワーク接続には有線ネットワークを使用することをお勧めします。私自身もこの経験があります。

オペレーティングシステムとPythonについては、もちろん64ビットを選択してください。 32 ビット オペレーティング システムを使用している場合は、大きなメモリを使用できません。 32 ビット Python を使用している場合、小規模なデータをキャプチャする場合は問題がないかもしれませんが、大量のデータを格納するリスト、キュー、ディクショナリなど、データ量が大きくなると、原因 Python のメモリ使用量が 2g を超えると、メモリ オーバーフロー エラーが報告されます。その理由は、私がかつてセグメントフォルトで尋ねた質問に対するエビアンの回答で説明されています (メモリ使用量が 1.9G に達する限り、java-python httplib モジュールはメモリ オーバーフロー エラーの報告を開始します - SegmentFault)

データの保存に mysql を使用する予定がある場合mysql5.5 バージョンは json データ型をサポートしているため、mongodb を放棄できるため、mysql5.5 以降のバージョンを使用することをお勧めします。 (mysql は mongodb よりも安定しているという人もいますが、私にはこれについてはわかりません。)

Python に関しては、バージョン 3.x が利用可能になったのに、なぜここでまだ python2.7 を使用しているのでしょうか?個人的にバージョン 2.7 を選択した理由は、昔購入した Python コア プログラミングの本が第 2 版であり、サンプル バージョンとしてまだ 2.7 を使用しているためです。また、バージョン 2.7 はいくつかの点で 3.x とは大きく異なるため、インターネット上には依然として 2.7 を使用するチュートリアル資料が多数あります。2.7 を学習していないと、その原因となるいくつかの微妙な構文の違いが理解できない可能性があります。私たちの理解にズレがあるか、デモコードを理解できません。また、バージョン 2.7 とのみ互換性のある依存パッケージがまだいくつかあります。私の提案は、あなたが Python を学び、その後会社で働きたいと思っていて、その会社に保守する古いコードがない場合、十分な時間があり、Python を持っていない場合は、3.x を直接開始することを検討してはいかがでしょうか。非常に体系的な専門家が指導するため、インターネット上に散在するブログ記事に頼って学習するしかないため、最初に 2.7 を学習してから 3.x を学習することをお勧めします。結局のところ、2.7 を学習した後はすぐに 3.x を始めることができます。

マルチスレッド クローラーに関連するナレッジ ポイント:

実際、どのソフトウェア プロジェクトでも、このプロジェクトを作成するためにどのようなナレッジ ポイントが必要かを知りたければ、どのパッケージがこのプロジェクトのメイン エントリ ファイルにインポートされるかを観察できます。プロジェクト。

それでは、Python を初めて使用する人として、ほとんど使用されたことのないパッケージがいくつかあるかもしれません。そこで、このセクションでは、これらのパッケージの機能とその方法について簡単に説明します。どのような知識ポイントが関係するのか、そしてそれらの知識ポイントのキーワードは何なのか。この記事では基本から始めるのにそれほど時間はかかりません。そのため、Baidu を上手に活用し、これらの知識ポイントのキーワードを検索して自分自身を教育する必要があります。これらの知識ポイントを 1 つずつ分析してみましょう。

HTTP プロトコル:

基本的に、クローラーは継続的に http リクエストを開始し、http レスポンスを取得し、それらをコンピューターに保存することによってデータをキャプチャします。 http プロトコルを理解すると、キープアライブなど、データをクロールするときにクロールを高速化できるいくつかのパラメーターを正確に制御するのに役立ちます。

スレッドモジュール (マルチスレッド):

私たちが通常書くプログラムは、すべてメインスレッドで実行され、このメインスレッドは Python プロセスで実行されます。スレッドとプロセスの説明については、Ruan Yifeng のブログを参照してください: プロセスとスレッドの簡単な説明 – Ruan Yifeng のオンライン ログ

マルチスレッドは、Python ではスレッド化と呼ばれるモジュールを通じて実装されます。以前はスレッド モジュールもありましたが、スレッドの制御がより強力になったため、後にスレッドに切り替えてマルチスレッド プログラミングを実装しました。

スレッドとマルチスレッドの使用法については、この記事が良いと思います: [Python] トピック 8. マルチスレッド プログラミングにおけるスレッドとスレッド 参考にしていただけます。

簡単に言うと、スレッド モジュールを使用してマルチスレッド プログラムを作成するには、まず自分でクラスを定義し、次にこのクラスが threading.Thread を継承し、各スレッドによって実行される作業コードを run に記述する必要があります。もちろん、スレッドの作成時にスレッド自体が初期化作業を行う必要がある場合は、その初期化作業のために実行されるコードをその __init__ メソッドに記述する必要があります。このメソッドは、PHP のコンストラクター メソッドとまったく同じです。そしてジャワ。

ここでさらに説明すべき点は、スレッド セーフの概念です。通常、シングルスレッドの状況では、各瞬間にリソース (ファイル、変数) を操作しているスレッドは 1 つだけであるため、競合が発生する可能性はほとんどありません。ただし、マルチスレッドの場合、2 つのスレッドが同時に同じリソースを操作し、リソースにダメージを与える可能性があるため、この競合によって引き起こされるダメージを解決するメカニズムが必要であり、これには通常、ロックやその他の操作が含まれます。たとえば、mysql データベースの innodb テーブル エンジンには行レベルのロックなどがあり、ファイル操作には読み取りロックなどがあります。これらはすべて、プログラムの最下位層によって完了します。したがって、通常は、それらの操作、またはスレッド セーフティの問題に対処するプログラムを知るだけで、マルチスレッド プログラミングでそれらを使用できるようになります。このようにスレッドセーフ性を考慮したプログラムを一般に「スレッドセーフ版」と呼びますが、例えばPHPにはTS版があり、このTSとはスレッドセーフのことです。以下で説明する Queue モジュールはスレッドセーフなキュー データ構造であるため、マルチスレッド プログラミングで安心して使用できます。

最後に、スレッドのブロックという重要な概念について説明します。スレッド モジュールを詳細に学習した後は、おそらくスレッドを作成して開始する方法がわかるでしょう。しかし、スレッドを作成してから start メソッドを呼び出すと、プログラム全体がすぐに終了することがわかります。何が起こっているのでしょうか?実際、これはメインスレッド内にサブスレッドを起動するコードしかないためです。つまり、サブスレッドによって実行されるコードに関しては、メインスレッドにはサブスレッドを起動する機能しかありません。それらは本質的にはクラスに書かれた単なるメソッドであり、実際にはメインスレッドで実行されるわけではないため、メインスレッドがサブスレッドを開始すると、すべての作業が完了し、正常に終了します。メインスレッドが終了すると、Python プロセスは終了し、他のスレッドには実行を継続するためのメモリ領域がなくなります。したがって、すべてのサブスレッド兄弟が実行を完了するまでメインスレッド兄弟を待たせてから、メインスレッドを妨害するメソッドはスレッドオブジェクトにあるのでしょうか。スレッド.スリープ?これは確かに解決策ですが、メインスレッドはどのくらいの時間スリープする必要があるのでしょうか?タスクを完了するのにどれくらい時間がかかるか正確に分からないため、この方法は絶対に使用できません。したがって、現時点では、サブスレッドをメインスレッドに「スタック」させる方法があるかどうかをオンラインで確認する必要がありますか? 「スタック」という言葉は下品すぎるように思えますが、より専門的に言うと「ブロッキング」と呼ぶべきなので、検索エンジンを正しく使用すれば、「Python サブスレッドがメインスレッドをブロックする」というクエリを実行できるはずです。はい、この join() メソッドは、サブスレッドが実行を完了していないときにメインスレッドをブロックするために使用されるメソッドです。 join() メソッドを含む行に到達すると、すべてのスレッドの実行が終了するまで、join() メソッドに続くコードは実行されません。

キュー モジュール (キュー):

ある人のブログをクロールする必要があるシナリオがあるとします。この人のブログには 2 つのページがあり、list.php ページにはこのブログのすべての記事リンクが表示されます。これは、記事の特定のコンテンツを表示する view.php ページでもあります。

この人のブログのすべての記事コンテンツをクロールしたい場合、シングルスレッド クローラーを作成するという考えは次のとおりです。まず正規表現を使用して、このリスト内のすべてのリンクの a タグの href 属性をクロールします。 .php ページを作成し、それを保存します。article_list という名前の配列 (Python では配列とは呼ばれません。リスト、中国語名のリストと呼ばれます) を入力し、for ループを使用してarticle_list 配列を走査し、さまざまな関数を使用します。 Web ページのコンテンツをキャプチャして、データベースに保存します。

このタスクを完了するためにマルチスレッド クローラーを作成したい場合は、プログラムが 10 個のスレッドを使用すると仮定して、以前にクロールされたarticle_list を 10 個の等しい部分に分割し、各部分を 1 つに個別に分配する方法を見つける必要があります。子スレッドの。

しかし、ここで問題が発生します。article_list 配列の長さが 10 の倍数ではない場合、つまり、記事の数が 10 の整数倍ではない場合、最後のスレッドには他のスレッドよりも少ないタスクが割り当てられます。そうすればすぐに終わるでしょう。

この種のわずか数千語のブログ記事をクロールするだけであれば、これは問題ないようですが、タスクがある場合 (必ずしも Web ページをクロールするタスクではなく、数学的な計算やグラフィックのレンダリングである可能性があります) 、など、時間がかかります。タスクの実行時間は非常に長く、リソースと時間の多大な無駄が発生します。マルチスレッドの目的は、すべてのコンピューティング リソースと計算時間を可能な限り活用することです。そのため、より科学的かつ合理的にタスクを割り当てる方法を見つける必要があります。

そして、状況も考慮する必要があります。つまり、記事の数が多い場合、記事のコンテンツを素早くクロールし、クロールしたコンテンツをできるだけ早く確認できる必要があります。この要件は多くの場合に発生します。これはCMSのまとめサイトに反映されることが多いです。

たとえば、現在クロールしたいターゲットブログには数千万の記事があります。通常、この場合、ブログはページ分割されます。したがって、上記の従来の考え方に従って、少なくとも list.php のすべてのページをクロールするとします。所要時間はわずか数時間、場合によっては数日です。上司が、クロールされたコンテンツをできるだけ早く表示し、CMS 収集ステーションに表示できるようにすることを望んでいる場合は、list.php を同時にクロールする必要があります。そして、キャプチャしたデータをarticle_list配列に投入し、別のスレッドを使用してarticle_list配列からキャプチャした記事のURLアドレスを抽出し、このスレッドを使用して正規表現を使用して、対応するURLアドレスからブログを取得します。この機能を実装するにはどうすればよいでしょうか?

2 つのタイプのスレッドを同時に開く必要があります。1 つのタイプのスレッドは、具体的には list.php 内の URL を取得し、それをarticle_list 配列にスローする役割を担います。 Article_list から抽出し、対応する view.php ページから抽出して、対応するブログのコンテンツを取得します。

しかし、前に述べたスレッド セーフの概念をまだ覚えているでしょうか?前者のタイプのスレッドは、article_list 配列にデータを書き込み、もう 1 つのタイプのスレッドは、article_list からデータを読み取り、読み取ったデータを削除します。ただし、Python の list はスレッドセーフなバージョンのデータ構造ではないため、この操作では予期しないエラーが発生します。したがって、より便利でスレッドセーフなデータ構造、つまりサブタイトルで言及した Queue キュー データ構造の使用を試みることができます。

同様に、Queue にも join() メソッドがあります。この join() メソッドは、実際には前のセクションで説明したスレッドの join() メソッドと似ていますが、Queue では join() のブロック条件がキューは空ではありません。空の場合にのみブロックされます。空でない場合は、join() の後にコードの実行が続行されます。このクローラーでは、スレッドの join メソッドを通じてメイン スレッドを直接ブロックするのではなく、このメソッドを使用してメイン スレッドをブロックしました。この方法の利点は、まだ存在するかどうかを確認するために無限ループを作成する必要がないことです。現在のタスク キュー内の未完了のタスクを削除し、プログラムをより効率的に実行し、コードをより洗練させます。

もう1つの詳細は、python2.7のキューモジュールの名前はQueueですが、python3では名前がqueueに変更されているという違いです。

getopt モジュール:

C 言語を学習したことがある方は、このモジュールに精通しているはずです。これは、コマンド ラインのコマンドから添付パラメータを抽出する役割を担うモジュールです。たとえば、通常、mysql データベースをコマンドラインで操作する場合、mysql -h127.0.0.1 -uroot -p と入力します。ここで、mysql の後の「-h127.0.0.1 -uroot -p」はパラメータ部分であり、取得できる。

通常、クローラーを作成する場合、mysql のホスト IP、ユーザー名、パスワードなど、ユーザーが手動で入力する必要があるパラメーターがいくつかあります。プログラムをより使いやすく、多用途にするために、一部の構成項目をコード内でハードコーディングする必要はありませんが、実行時にそれらを動的に渡すことで、この機能を実現できます。

hashlib (ハッシュ):

ハッシュは本質的に数学的アルゴリズムの集合体であり、この数学的アルゴリズムの特徴は、パラメータを与えると別の結果を出力できることです。この結果は非常に短いものですが、近似的に考えることができます。個性的。たとえば、通常、md5、sha-1 などを聞きますが、これらはすべてハッシュ アルゴリズムに属します。一連の数学的演算を行った後、一部の文書やテキストを、100 桁未満の数字と英語が混在した文字列に変換できます。

Python の hashlib モジュールは、これらの数学演算関数をカプセル化しています。これを呼び出すだけでハッシュ演算を完了できます。

このパッケージをクローラーで使用するのはなぜですか?一部のインターフェイス要求では、インターフェイスによって要求されたデータが改ざんされたり紛失したりしていないことを確認するためにサーバーがいくつかの検証コードを取得する必要があるため、これらの検証コードは通常ハッシュ アルゴリズムであるため、この操作を完了するにはこのモジュールを使用する必要があります。 。

json:

多くの場合、私たちがキャプチャするデータは HTML ではなく、一部の JSON データです。json は本質的に、特定の文字列を抽出する必要がある場合、これを変換する必要があります。 json 文字列を便宜上 dict 型に変換します。

re (正規表現):

Web コンテンツをキャプチャすることがありますが、Web ページから一部のコンテンツを特定の形式で抽出する必要がある場合、通常、電子メール アドレスの形式は最初の数文字です。数字と文字、@ 記号、および http://xxx.xxx のドメイン名。この形式をコンピューター言語で記述するには、正規表現と呼ばれる式を使用して、コンピューターが自動的にテキストを照合します。大きな文字列からこの特定の形式に一致します。

sys:

このモジュールは主にいくつかのシステム問題に対処するために使用され、このクローラーでは出力エンコーディングの問題を解決するために使用します。

time:

少し英語を学んだ人なら、このモジュールが時間の処理に使用されていることが推測できるでしょう。このクローラーでは、それを使用して現在のタイムスタンプを取得し、プログラムの最後で現在のタイムスタンプを減算します。メインスレッドの実行開始時のタイムスタンプを取得して、プログラムの実行時間を取得します。

図に示すように、100 ページをクロールするために 50 のスレッドが開かれます (ページあたり 30 件の投稿、3000 件の投稿のクロールに相当)。Tieba の投稿コンテンツと携帯電話のメール アドレスの抽出のこのステップには合計 330 時間がかかります。秒。

urllib と urllib2:

これら 2 つのモジュールは、一部の http リクエストと URL フォーマットを処理するために使用されます。クローラーの http リクエスト部分のコア コードは、このモジュールを使用して完成します。

MySQLdb:

これは、Python で mysql データベースを操作するためのサードパーティ モジュールです。

ここで、細部に注意する必要があります。mysqldb モジュールはスレッドセーフ バージョンではありません。つまり、複数のスレッドで同じ mysql 接続ハンドルを共有することはできません。したがって、私のコードでは、各スレッドのコンストラクターで新しい mysql 接続ハンドルを渡していることがわかります。したがって、各子スレッドは独自の独立した mysql 接続ハンドルのみを使用します。

cmd_color_printers:

これも、関連するコードがオンラインで見つかります。このモジュールは、主にコマンド ラインにカラー文字列を出力するために使用されます。たとえば、通常、クローラでエラーが発生したときに、より目立つ赤いフォントを出力したい場合は、このモジュールを使用する必要があります。

自動クローラのエラー処理:

ネットワーク品質があまり良くない環境でこのクローラを使用すると、図に示すような例外が報告されることがあります。さまざまな例外処理ロジックを怠惰に書いたわけではありません。

通常、高度に自動化されたクローラーを作成したい場合は、クローラーが遭遇する可能性のあるすべての異常な状況を予測し、これらの異常な状況に対処する必要があります。

例えば、図に示すようなエラーが発生した場合、その時点で処理中のタスクをタスクキューに再挿入する必要があり、そうしないと情報が欠落してしまいます。これは、クローラーの作成において複雑な点でもあります。

概要:

実際、マルチスレッド クローラーの作成は複雑ではありません。サンプル コードを読んだり、自分で試したり、コミュニティやフォーラムにアクセスしてコミュニケーションしたり、多くの古典的な書籍にもマルチスレッド プログラミングについての非常に詳細な説明が記載されています。この記事は基本的に一般的な科学記事であり、内容はそれほど深くはありません。それでも、さまざまなオンライン教材を組み合わせて授業外に自分で勉強する必要があります。

以上がPython を使用してマルチスレッド クローラーを作成し、Baidu Tieba の電子メール アドレスと携帯電話番号を取得するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。