4

特定の URL のテキストを取得するという 1 つの非常に特定の目的のために、ウィキペディアにクエリを実行する必要があります。もう少し正確に言うと:

私は約 14,000 のウィキペディアの英語コーパスの URL を持っており、テキスト、または少なくともこれらの各 URL の紹介を取得する必要があります。今後の処理は Python で行うため、これが最適な言語になります。

私は最高のパフォーマンスを発揮する方法を探しており、4 つの異なるアプローチを作成しました。

  1. xml ダンプを取得し、python を介して直接解析します
    -> ここでのさらなる質問は次のとおりです: URL を知って、xml ファイルを照会する方法は?
  2. xml を取得し、データベースをセットアップし、sqlpython でクエリを実行します
    -> ここでさらに質問があります: URL を知って、SQL をクエリする方法は?
  3. ウィキペディア API を使用し、Python 経由で直接クエリを実行する
  4. これらのウィキペディアのページをクロールするだけです (これは、HTML でプレーン テキストがないため、おそらく卑劣で迷惑です)。

どの方法を使用する必要がありますか、つまり、どの方法が最高のパフォーマンスを発揮し、何らかの形で標準的ですか?

4

2 に答える 2

8

いくつかの考え:

私は約 14,000 のウィキペディアの英語コーパスの URL を持っており、テキスト、または少なくともこれらの各 URL の紹介を取得する必要があります。

1 - xml ダンプを取得し、python 経由で直接解析する

現在、英語版ウィキペディアには 4,140,​​640 件の記事があります。あなたが興味を持っている記事は 14,000 件、つまり全体の約 3 分の 1 です。これはまばらすぎて、すべての記事をダンプするのが最善の方法ではないように思えます。

2 - xml を取得し、データベースをセットアップして、Python で SQL をクエリします

あなたが興味を持っている一連の記事が増えたり変化したりすることを期待していますか? 一連の記事の変更に迅速に対応する必要がある場合は、ローカル データベースが役立つ場合があります。ただし、最新の状態に保つ必要があります。十分に高速であれば、API を使用してライブ データを取得する方が簡単です。

4 - これらのウィキペディアのページをクロールするだけです (これは、HTML でプレーン テキストがないため、ちょっと卑劣で迷惑な場合もあります)

必要なものを API から取得できれば、ウィキペディアのサイトをスクレイピングするよりも効果的です。

3 - ウィキペディア API を使用し、Python 経由で直接クエリを実行します

関心のある記事の割合が 0.338% と低いことに基づくと、これがおそらく最良のアプローチです。

The MediaWiki API documentationAPI Referenceを確認してください。python-wikitools モジュールもあります。

テキスト、または少なくとも導入部を取得する必要があります

イントロだけが本当に必要な場合は、トラフィックを大幅に節約でき、API を使用することが断然最良の選択になります。

イントロダクションを取得するにはさまざまな方法がありますが、ここに 1 つの良い方法があります。

http://en.wikipedia.org/w/api.php?action=query&prop=extracts&exintro&format=xml&titles=Python_(プログラミング言語)

一度に処理するリクエストが多数ある場合は、最大 20 個の記事のグループにまとめてバッチ処理できます。

http://en.wikipedia.org/w/api.php?action=query&prop=extracts&exintro&exlimit=20&format=xml&titles=Python_(programming_language)|History_of_Python|Guido_van_Rossum

これにより、700 回の往復で 14,000 件の記事紹介を取得できます。

注: API リファレンス exlimitドキュメントには次のように記載されています。

最大 20 (ボットの場合は 20) まで許可

また、注: エチケットと使用制限に関するAPIドキュメントのセクションには、次のように記載されています。

リクエストを並列ではなく連続して行う場合 (つまり、1 つのリクエストが完了するのを待ってから新しいリクエストを送信し、同時に複数のリクエストを行うことがないようにする場合) は、間違いなく問題ありません。また、可能な場合は 1 つのリクエストにまとめるようにしてください (たとえば、タイトルごとに新しいリクエストを作成する代わりに、titles パラメータで複数のタイトルを使用します。

ウィキペディアは常に更新されています。データを更新する必要がある場合は、リビジョン ID とタイムスタンプを追跡することで、古いローカル記事を特定できます。次の例を使用して、リビジョン情報を取得できます(イントロとともに、ここでは複数の記事を含む):

http://en.wikipedia.org/w/api.php?action=query&prop=revisions|extracts&exintro&exlimit=20&rvprop=ids|timestamp&format=xml&titles=Python_(programming_language)|History_of_Python|Guido_van_Rossum

于 2013-01-10T14:21:21.580 に答える
0

これも答えの一部にすぎません。ジムハークが提案した可能な解決策の1つについて、自分自身をプロファイリングしました。

ウィキペディアの API

に保存されたこの小さなコードを使用しましたquery.py

import urllib2
import xml.etree.ElementTree as ET
import numpy as np

for i in np.arange(0,1000):
    url = 'http://en.wikipedia.org/w/api.php?format=xml&action=query&titles=Fish&prop=revisions&rvprop=content'
    response = urllib2.urlopen(url)
    html_string = response.read()
    a = ET.fromstring(html_string)
    try :
        a.find('query').find('pages').find('page').find('revisions').find('rev').text
    except (AttributeError):
        pass

そして走っpython -m cProfile query.pyた。

ほとんどの場合、Wikipeda API はクエリを のページにキャッシュするため、これはあまりスマートなプロファイリングではありませんfish

結果:

1431056 function calls (1412734 primitive calls) in 686.813 seconds

ほとんどすべての場合:

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
118081  644.566    0.005  644.566    0.005 {method 'recv' of '_socket.socket' objects}

これを私のデータセットに採用してお知らせします。

于 2013-01-10T15:21:58.713 に答える