使用bs4从表的标题中提取信息

时间:2016-06-04 23:01:49

标签: python html bs4

我正在尝试使用bs4和python从表中提取信息。 当我使用以下代码从表的标题中提取信息时:

    tr_header=table.findAll("tr")[0]
    tds_in_header = [td.get_text()  for td in tr_header.findAll("td")]
    header_items= [data.encode('utf-8')  for data in tds_in_header]
    len_table_header = len (header_items)

它有效,但对于以下代码,我试图从表的第一行到结尾提取信息:

    tr_all=table.findAll("tr")[1:]
    tds_all = [td.get_text()  for td in tr_all.findAll("td")]
    table_info= [data.encode('utf-8')  for data in tds_all]

出现以下错误:

AttributeError: 'list' object has no attribute 'findAll'

任何人都可以帮我编辑它。

这是表格信息:

    <table class="codes"><tr><td><b>Code</b>
</td><td><b>Display</b></td><td><b>Definition</b></td>
</tr><tr><td>active<a name="active"> </a></td>
<td>Active</td><td>This account is active and may be used.</td></tr>
<tr><td>inactive<a name="inactive"> </a></td>
<td>Inactive</td><td>This account is inactive
 and should not be used to track financial information.</td></tr></table>

这是tr_all的输出:

[<tr><td><b>Code</b></td><td><b>Display</b></td><td><b>Definition</b></td></tr>, <tr><td>active<a name="active"> </a></td><td>Active</td><td>This account is active and may be used.</td></tr>, <tr><td>inactive<a name="inactive"> </a></td><td>Inactive</td><td>This account is inactive and should not be used to track financial information.</td></tr>] 

2 个答案:

答案 0 :(得分:1)

关于你的第一个问题,

import bs4

text = """
<table class="codes"><tr><td><b>Code</b>
</td><td><b>Display</b></td><td><b>Definition</b></td>
</tr><tr><td>active<a name="active"> </a></td>
<td>Active</td><td>This account is active and may be used.</td></tr>
<tr><td>inactive<a name="inactive"> </a></td>
<td>Inactive</td><td>This account is inactive
 and should not be used to track financial information.</td></tr></table>"""

table = bs4.BeautifulSoup(text)
tr_all = table.findAll("tr")[1:]
tds_all = []
for tr in tr_all:
    tds_all.append([td.get_text() for td in tr.findAll("td")])
    # if You prefer double list comprefension instead...
table_info = [data[i].encode('utf-8') for data in tds_all
                                      for i in range(len(tds_all))]
print(table_info)

产量

['active ', 'Active', 'inactive ', 'Inactive']

关于你的第二个问题

  

tr_header = table.findAll(“tr”)[0]我没有列表

是的,[]是索引操作,它从列表中选择第一个元素,因此您获得单个元素。 [1:]正在切片运算符(如果需要更多信息,请查看nice tutorial)。

实际上,对于每次调用table.findAll(“tr”),你会得到两次列表 - 用于标题和其余行。当然,这是多余的。 如果你想从标题和休息中分离标记,我想你可能想要这样的东西

tr_all = table.findAll("tr")
header = tr_all[0]
tr_rest = tr_all[1:] 
tds_rest = []
header_data = [td.get_text().encode('utf-8') for td in header]

for tr in tr_rest:
     tds_rest.append([td.get_text() for td in tr.findAll("td")])

关于第三个问题

  

是否可以编辑此代码以将表信息从第一行添加到表的末尾?

在下面的评论中给出您想要的输出:

rows_all = table.findAll("tr")
header = rows_all[0]
rows = rows_all[1:]

data = []
for row in rows:
    for td in row:
        try:
            data.append(td.get_text())
        except AttributeError:
            continue
print(data)

# or more or less same as above, oneline
data = [td.get_text() for row in rows for td in row.findAll("td")]

产量

[u'active', u'Active', u'This account is active and may be used.', u'inactive', u'Inactive', u'This account is inactive and should not be used to track financial information.']

答案 1 :(得分:0)

JustMe正确回答了这个问题。 另一个等效的变体是:

function testAjax(handleData) {
  $.ajax({
    url:"getvalue.php",  
    success:function(data) {
      handleData(data); 
    }
  });
}

关键行中的这种奇怪结构可以使列表列表变得扁平化[tds_all&#39; lambda z:[x代表y中的y代表y中的x]平展列表z的列表。我根据这种具体情况替换了x和y和z。

实际上我来到了它,因为我作为一个中间步骤作为关键线: tds_all = [[td.get_text()for td in each_tr.findAll(&#34; td&#34;)] for each_tr in tr_all] 它生成tds_all的列表列表: [[u&#39;有效&#39;,你&#39;有效&#39;,你&#39;此帐户有效,可能会被使用。&#39;],[u&#39;无效&#39; ,u&#39;无效&#39;,u&#39;此帐户处于无效状态\ n,不应用于跟踪财务信息。&#39;]] 为了使这一点变得平坦,人们需要这个[x代表y中的y表示y]。 但后来我想,为什么不将这个结构直接应用到临界线并由此展平呢?

z是bs4-objects(tr_all)的列表。在这个&#39; for ... in ...&#39; -construct中,each_tr(一个bs4-object)取自列表&lt; tr_all&#39 ;, each_tr对象在后面生成&#39; for-in&#39; - 构建所有&#39;&#39;通过表达式each_tr.findAll(&#34; td&#34;)匹配,每个匹配&#34; td&#34;被这背后隔离了......在...&#39; -loop中,并且在这个听众的最开始时,应该在最终列表中收集什么: 与此对象隔离的文本(&#34; td.get_text()&#34;)。最终的结果列表将分配给td_all。

此代码的结果是此结果列表:

$.ajax({

    url: "post.php",
    data: {
        id: 123
    },
    method: "GET",
    dataType : "json",
})
  .done(function( json ) {
     $( "<h1>" ).text( json.title ).appendTo( "body" );
     $( "<div class=\"content\">").html( json.html ).appendTo( "body" );
  })

示例中缺少两个较长的元素是JustMe。我想,玛丽,你想把它们包括在内,不是吗?