2011-11-01 2 views
-1

私は、すべてのプレーンリンク、または文字列のすべてのアンカータグを解析する他の質問を見たことがありますが、その両方を行うものはありません。文字列からすべてのアンカータグまたはリンクを抽出する正規表現を作成するにはどうすればよいですか?

理想的には、正規表現が(私は、Pythonを使用しています)、このような文字列を解析することができるようになります:

>>> import re 
>>> content = ' 
    <a href="http://www.google.com">http://www.google.com</a> Some other text. 
    And even more text! http://stackoverflow.com 
    ' 
>>> links = re.findall('some-regular-expression', content) 
>>> print links 
[u'http://www.google.com', u'http://stackoverflow.com'] 

はそれが重複したリンクが返されを生じない正規表現を生成することが可能です?これを行うより良い方法はありますか?

+2

私はPythonの人ではないですので、私は何を使うべきかを正確に伝えることはできませんが、HTMLを解析するための正規表現を探し始めるたびに、答えは正規表現を使用しません!あなたのためにHTMLを解析する良いモジュールを見つけてください。 – Nick

+0

すべての可能なURLを検出しようとしていますか、より一般的なものだけを検出しようとしていますか? RegexはすべてのURLに完全にマッチさせるのは難しいビジネスです - http://mathiasbynens.be/demo/url-regex –

+0

@ShawnChin URLを検証することはそれほど難しくありませんか? ? –

答えて

1

あなたが何をしても、それは面倒です。それにも関わらず、90%のソリューションは似ているかもしれません:

r'<a\s[^>]*>([^<]*)</a>|\b(\w+://[^<>\'"\t\r\n\xc2\xa0]*[^<>\'"\t\r\n\xc2\xa0 .,()])' 

そのパターンは2つのグループを持っているので、それが2タプルのリストを返します。それらを結合するには、リストの内包あるいはマップを使用することができます。

r'<a\s[^>]*src=[\'"]([^"\']*)[\'"][^>]*>[^<]*</a>|\b(\w+://[^<>\'"\t\r\n\xc2\xa0]*[^<>\'"\t\r\n\xc2\xa0 .,()])' 

:あなたが代わりにリンク・テキストのアンカーのsrc属性をしたい場合は、パターンがさえメシエを取得

map(''.join, re.findall(pattern, content)) 

あなたは肝炎たら

r'\b\w+://[^<>\'"\t\r\n\xc2\xa0]*[^<>\'"\t\r\n\xc2\xa0 .,()]' 

:別の方法として、あなただけのパターンの後半は、文字列が参加の必要性を軽減src属性を、ピックアップしてみましょうことができますあなたはリンクのように見えないもので置き換えられ、'://'を検索し、欠けているものを収集するためにパターンを更新することができます。偽陽性、特に最後のゴミを掃除する必要があるかもしれません。

警告:特にセキュリティがライン上にあるときにこれを頼りにしないでください。既存のデータから手動でリンクを収集する場合にのみ使用することをお勧めします。

-1

いいえ、このように文字列を解析することはできません。 Regexpは単純なマッチングが可能で、複雑な文法を1つまたは2つの正規表現でHTMLとして解析することはできません。

+0

"複雑な文法"文法 "なので、正規表現は正しいツールではありません。しかし、HTMLには文脈自由文法があります。 –

+0

1.有効なhtmlに文脈自由文法があるかもしれない 2.引用符やその他の終了記号を含む一致する属性を試してみる – Lachezar

1

通常、HTMLは通常の言語ではないため、you should never parse HTML with regular expressionsです。ここでは、すべてのhttpリンクをA要素またはテキストのいずれかにしたいだけです。どのようにそれらをすべて取得し、重複を削除するのですか?

set(re.findall("(http:\/\/.*?)[\"' <]", content)) 

のようなものを試してみて、それがあなたの目的を果たすかどうかを確認します。

+0

興味深いことに、XMLはドキュメント定義の正式な部分に禁止された 'a'ネストをSGML版のHTMLには*含まれています)。 –

+0

申し訳ありません@KerrekSB私は完全に間違った質問を読んで、それに応じて私の答えを変更しました。 –

0

すべての有効なURLと一致する正規表現パターンを書くのはtrickybusinessです。

あなたが探しているすべての任意の文字列シンプルなHTTP/HTTPSのURLを検出することであるならば、私はあなたにこのソリューションを提供できます。

>>> import re 
>>> content = '<a href="http://www.google.com">http://www.google.com</a> Some other text. And even more text! http://stackoverflow.com' 
>>> re.findall(r"https?://[\w\-.~/?:#\[\]@!$&'()*+,;=]+", content) 
['http://www.google.com', 'http://www.google.com', 'http://stackoverflow.com'] 

httpで始まる文字列を検索します://またはhttps://の後に1つ以上の有効な文字が続きます。

set()を使用し、重複したエントリを避けるために:

>>> list(set(re.findall(r"https?://[\w\-.~/?:#\[\]@!$&'()*+,;=]+", content))) 
['http://www.google.com', 'http://stackoverflow.com'] 
0

あなたがHTMLから物事を抽出するために正規表現を使用しないでください。 HTMLパーサーを使用する必要があります。

ページのテキストからも抽出したい場合は、別途行う必要があります。

ここでは、lxmlでそれを行うだろう方法は次のとおりです。

# -*- coding: utf8 -*- 

import lxml.html as lh 
import re 

html = """ 
is.gd/test<a href="http://www.google.com">http://www.google.com</a> Some other text. 
And even more text! http://stackoverflow.com 

here's a url bit.ly/test 


""" 

tree = lh.fromstring(html) 

urls = set([]) 

for a in tree.xpath('//a'): 
    urls.add(a.text) 

for text in tree.xpath('//text()'): 
    for url in re.findall(r'(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))', text): 
     urls.add(url[0]) 

print urls 

結果:ここから

set(['http://www.google.com', 'bit.ly/test', 'http://stackoverflow.com', 'is.gd/test']) 

URLのmatchine正規表現:http://daringfireball.net/2010/07/improved_regex_for_matching_urls

関連する問題