7

この質問が RTFM ではないことを願っています。<link href...標準の HTML Web ページ (タグ)からリンクを抽出する Python スクリプトを作成しようとしています。Web で一致する正規表現を検索したところ、さまざまなパターンが見つかりました。リンクを照合するための合意済みの標準正規表現はありますか?

アダム

更新: 私は実際に2つの異なる答えを探しています:

  1. HTML リンクを解析するためのライブラリ ソリューションは何ですか。美しいスープは良い解決策のようです(ありがとう、Igal Serbanそしてcletus!)
  2. 正規表現を使用してリンクを定義できますか?
4

8 に答える 8

17

HTML を含む正規表現は乱雑になります。Beautiful Soup のような DOM パーサーを使用するだけです。

于 2009-01-10T13:52:47.753 に答える
8

他の人が示唆しているように、リアルタイムのようなパフォーマンスが必要ない場合は、 BeautifulSoup が良い解決策です:

import urllib2
from BeautifulSoup import BeautifulSoup

html = urllib2.urlopen("http://www.google.com").read()
soup = BeautifulSoup(html)
all_links = soup.findAll("a")

2 番目の質問については、はい、HTML リンクは明確に定義されている必要がありますが、実際に遭遇する HTML が標準である可能性はほとんどありません。BeautifulSoup の優れた点は、ブラウザーのようなヒューリスティックを使用して、実際に遭遇する可能性が高い非標準の不正な形式の HTML を解析しようとすることです。

標準の XHTML で作業していることが確実な場合は、expat のような (はるかに) 高速な XML パーサーを使用できます。

上記の理由から (パーサーは状態を維持する必要があり、正規表現はそれを行うことができません)、正規表現は決して一般的な解決策にはなりません。

于 2009-01-10T17:53:02.963 に答える
5

いいえ、ありません。

Beautiful Soupの使用を検討できます。これは、html ファイルを解析するための標準と呼ぶことができます。

于 2009-01-10T13:53:19.797 に答える
4

リンクは明確に定義された正規表現であるべきではありませんか?

いいえ、[X]HTML は通常、正規表現で解析できません。次のような例を考えてみましょう:

<link title='hello">world' href="x">link</link>
<!-- <link href="x">not a link</link> -->
<![CDATA[ ><link href="x">not a link</link> ]]>
<script>document.write('<link href="x">not a link</link>')</script>

これはランダムに有効な例のほんの一部です。現実世界のタグスープ HTML に対処しなければならない場合、不正な形式の可能性が無数にあります。

ターゲットページの正確な出力形式を知っていて、信頼できる場合は、正規表現を使用できます。そうでなければ、ウェブページをスクレイピングするのは完全に間違った選択です。

于 2009-01-10T15:10:23.387 に答える
3

リンクは明確に定義された正規表現であるべきではありませんか? これはかなり理論的な質問ですが、

私は2番目のPEZの答え:

HTML は正規言語ではないため、「明確に定義された」正規表現には向いていないと思います。

私の知る限り、どの HTML タグにもネストされたタグをいくつでも含めることができます。例えば:

<a href="http://stackoverflow.com">stackoverflow</a>
<a href="http://stackoverflow.com"><i>stackoverflow</i></a>
<a href="http://stackoverflow.com"><b><i>stackoverflow</i></b></a>
...

したがって、原則として、タグを適切に照合するには、少なくとも次の形式の文字列を照合できる必要があります。

BE
BBEE
BBBEEE
...
BBBBBBBBBBEEEEEEEEEE
...

ここで、B はタグの開始を意味し、E は終了を意味します。つまり、任意の数の B の後に同数の E が続く文字列と一致する必要があります。そのためには、マッチャーが「カウント」できる必要がありますが、正規表現 (つまり、有限状態オートマトン) ではそれができません (カウントするには、オートマトンに少なくとも 1 つのスタックが必要です)。PEZ の回答を参照すると、HTML は文脈自由文法であり、通常の言語ではありません。

于 2009-01-10T15:50:51.307 に答える
1

HTML の生成方法によって多少異なります。ある程度制御されている場合は、次の方法で回避できます。

re.findall(r'''<link\s+.*?href=['"](.*?)['"].*?(?:</link|/)>''', html, re.I)
于 2009-01-10T14:19:18.620 に答える
1

そこであなたの2つのサブ質問に答えます。

  1. 私は時々 SGMLParser (コアの Python ディストリビューションに含まれています) をサブクラス化しましたが、それは簡単だと言わざるを得ません。
  2. HTML は正規言語ではないため、「明確に定義された」正規表現には向いていないと思います。
于 2009-01-10T14:24:30.467 に答える
0

質問 2 (リンクは適切に定義された正規表現であってはならない) に対する答えは ... いいえです。

HTML のリンク構造は、プログラミング言語のかっこや中かっこのように再帰的です。開始構成と終了構成は同数でなければならず、「リンク」式はそれ自体にネストできます。

「リンク」式を適切に一致させるには、開始タグと終了タグをカウントする正規表現が必要です。正規表現は、有限オートマトンのクラスです。定義により、有限オートマトンはパターン内の構造を「カウント」できません。このような再帰的なデータ構造を記述するには、文法が必要です。正規表現を「カウント」できないことが、プログラミング言語が正規表現ではなく文法で記述されている理由です。

そのため、すべての「リンク」式の 100% に確実に一致する正規表現を作成することはできません。確かに、大量の「リンク」に高い精度で一致する正規表現がありますが、完全にはなりません。

最近、この問題についてブログ記事を書きました。 正規表現の制限

于 2009-01-10T15:48:48.423 に答える