どのように私は、HTMLファイルからの私に必要なデータを抽出していますか?
-
05-09-2019 - |
質問
これは私が持っているHTMLでます:
p_tags = '''<p class="foo-body">
<font class="test-proof">Full name</font> Foobar<br />
<font class="test-proof">Born</font> July 7, 1923, foo, bar<br />
<font class="test-proof">Current age</font> 27 years 226 days<br />
<font class="test-proof">Major teams</font> <span style="white-space: nowrap">Japan,</span> <span style="white-space: nowrap">Jakarta,</span> <span style="white-space: nowrap">bazz,</span> <span style="white-space: nowrap">foo,</span> <span style="white-space: nowrap">foobazz</span><br />
<font class="test-proof">Also</font> bar<br />
<font class="test-proof">foo style</font> hand <br />
<font class="test-proof">bar style</font> ball<br />
<font class="test-proof">foo position</font> bak<br />
<br class="bar" />
</p>'''
この美しいスープを使用して、私のPythonのコードです:
def get_info(p_tags):
"""Returns brief information."""
head_list = []
detail_list = []
# This works fine
for head in p_tags.findAll('font', 'test-proof'):
head_list.append(head.contents[0])
# Some problem with this?
for index in xrange(2, 30, 4):
detail_list.append(p_tags.contents[index])
return dict([(l, detail_list[head_list.index(l)]) for l in head_list])
私は、HTMLから適切head_list
を取得するが、detail_list
が動作していません。
head_list = [u'Full name', u'Born', u'Current age', u'Major teams', u'Also', u'foo style', u'bar style', u'foo position']
私はこのような何かをしたかった。
{ 'Full name': 'Foobar', 'Born': 'July 7, 1923, foo, bar', 'Current age': '78 years 226 days', 'Major teams': 'Japan, Jakarta, bazz, foo, foobazz', 'Also': 'bar', 'foo style': 'hand', 'bar style': 'ball', 'foo position': 'bak' }
すべてのヘルプはかなりのだろう。事前に感謝します。
解決
不必要に複雑なコードのために申し訳ありませんが、私はひどくカフェインの大線量を必要とする;)
import re
str = """<p class="foo-body">
<font class="test-proof">Full name</font> Foobar<br />
<font class="test-proof">Born</font> July 7, 1923, foo, bar<br />
<font class="test-proof">Current age</font> 27 years 226 days<br />
<font class="test-proof">Major teams</font> <span style="white-space: nowrap">Japan,</span> <span style="white-space: nowrap">Jakarta,</span> <span style="white-space: nowrap">bazz,</span> <span style="white-space: nowrap">foo,</span> <span style="white-space: nowrap">foobazz</span><br />
<font class="test-proof">Also</font> bar<br />
<font class="test-proof">foo style</font> hand <br />
<font class="test-proof">bar style</font> ball<br />
<font class="test-proof">foo position</font> bak<br />
<br class="bar" />
</p>"""
R_EXTRACT_DATA = re.compile("<font\s[^>]*>[\s]*(.*?)[\s]*</font>[\s]*(.*?)[\s]*<br />", re.IGNORECASE)
R_STRIP_TAGS = re.compile("<span\s[^>]*>|</span>", re.IGNORECASE)
def strip_tags(str):
"""Strip un-necessary <span> tags
"""
return R_STRIP_TAGS.sub("", str)
def get_info(str):
"""Extract useful info from the given string
"""
data = R_EXTRACT_DATA.findall(str)
data_dict = {}
for x in [(x[0], strip_tags(x[1])) for x in data]:
data_dict[x[0]] = x[1]
return data_dict
print get_info(str)
他のヒント
私は、私はあなたが「美しいスープ」を使用していたが実現する前にこれを答える始めたが、ここで私はあなたの例の文字列を持つ作品はHTMLParserライブラリ
を使用して書かれたと思わパーサですfrom HTMLParser import HTMLParser
results = {}
class myParse(HTMLParser):
def __init__(self):
self.state = ""
HTMLParser.__init__(self)
def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
if tag == "font" and attrs.has_key("class") and attrs['class'] == "test-proof":
self.state = "getKey"
def handle_endtag(self, tag):
if self.state == "getKey" and tag == "font":
self.state = "getValue"
def handle_data(self, data):
data = data.strip()
if not data:
return
if self.state == "getKey":
self.resultsKey = data
elif self.state == "getValue":
if results.has_key(self.resultsKey):
results[self.resultsKey] += " " + data
else:
results[self.resultsKey] = data
if __name__ == "__main__":
p_tags = """<p class="foo-body"> <font class="test-proof">Full name</font> Foobar<br /> <font class="test-proof">Born</font> July 7, 1923, foo, bar<br /> <font class="test-proof">Current age</font> 27 years 226 days<br /> <font class="test-proof">Major teams</font> <span style="white-space: nowrap">Japan,</span> <span style="white-space: nowrap">Jakarta,</span> <span style="white-space: nowrap">bazz,</span> <span style="white-space: nowrap">foo,</span> <span style="white-space: nowrap">foobazz</span><br /> <font class="test-proof">Also</font> bar<br /> <font class="test-proof">foo style</font> hand <br /> <font class="test-proof">bar style</font> ball<br /> <font class="test-proof">foo position</font> bak<br /> <br class="bar" /></p>"""
parser = myParse()
parser.feed(p_tags)
print results
の結果が得られます。
{'foo position': 'bak',
'Major teams': 'Japan, Jakarta, bazz, foo, foobazz',
'Also': 'bar',
'Current age': '27 years 226 days',
'Born': 'July 7, 1923, foo, bar' ,
'foo style': 'hand',
'bar style': 'ball',
'Full name': 'Foobar'}
問題は、あなたのHTMLは非常によく考え抜かれていないということです - あなたはあなたのラベルとデータがインターリーブされている「混合コンテンツモデル」を持っています。あなたのラベルは<font>
タグに包まれたが、あなたのデータはNavigableStringノードであるされています。
あなたはp_tag
の内容を反復処理する必要があります。ノードの2種類があります:。(あなたのTag
タグを持っている)<font>
ノードとテキストの他のビットを持ってNavigableString
ノード
from beautifulsoup import *
label_value_pairs = []
for n in p_tag.contents:
if isinstance(n,Tag) and tag == "font"
label= n.string
elif isinstance(n, NavigableString):
value= n.string
label_value_pairs.append( label, value )
else:
# Generally tag == "br"
pass
print dict( label_value_pairs )
約そのような何かます。
あなたは>が先行し、<、末尾を無視するか、先頭の空白が続く文字列を検索します。あなたは助けることができる文字列内の各文字を見てループ、または正規表現を非常に簡単にこれを行うことができます。 > [\ t]は*のようなもの[^ <] + [T \] * <ます。
また、使用することができます re.split とタグの内容を表す正規表現、<[^>] *>スプリッタとして、あなたは、アレイ内のいくつかの空のエントリを取得しますのようなものが、これらは簡単に削除されます。