2009-02-18 90 views
2

这是HTML我有:我如何从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_listdetail_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' 
} 

任何帮助将是明显的。提前致谢。

回答

2

很抱歉的不必要的复杂代码,我很喜欢咖啡因的大剂量;)

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) 
0

您想要查找以>开头的字符串,然后是<,忽略尾随或前导空格。你可以很容易地用循环来查看字符串中的每个字符,或者正则表达式可以提供帮助。就像> [\ t] * [^ <] + [\ t] * <。

你也可以使用re.split和代表标签内容的正则表达式,就像< [^>] *>作为分隔符,你会在数组中获得一些空条目,但是这些条目很容易被删除。

4

问题在于您的HTML没有经过深思熟虑 - 您有一个“混合内容模型”,您的标签和数据交错存在。您的标签包裹在<font>标签中,但您的数据位于NavigableString节点中。

您需要遍历p_tag的内容。将有两种节点: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) 

大概是这样的。

+0

如果isinstance(n,Tag) 这是什么标签? – aatifh 2009-02-19 06:59:09

4

我开始回答这个问题之前,我意识到你正在使用“美丽汤”,但这里有一个解析器,我认为作品你的榜样字符串使用的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'} 
相关问题