どのように私は、HTMLファイルからの私に必要なデータを抽出していますか?

StackOverflow https://stackoverflow.com/questions/560936

質問

これは私が持っている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 とタグの内容を表す正規表現、<[^>] *>スプリッタとして、あなたは、アレイ内のいくつかの空のエントリを取得しますのようなものが、これらは簡単に削除されます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top