Python HTML表到熊猫表:HTML标记中的信息

Python HTML表到熊猫表:HTML标记中的信息,python,pandas,beautifulsoup,Python,Pandas,Beautifulsoup,我有一个来自web的大表,通过请求访问并使用BeautifulSoup解析。它的一部分看起来像这样: <table> <tbody> <tr> <td>265</td> <td> <a href="/j/jones03.shtml">Jones</a>Blue</td> <td>29</td> </tr> <tr > <td>26

我有一个来自web的大表,通过请求访问并使用BeautifulSoup解析。它的一部分看起来像这样:

<table>
<tbody>
<tr>
<td>265</td>
<td> <a href="/j/jones03.shtml">Jones</a>Blue</td>
<td>29</td>
</tr>
<tr >
<td>266</td>
<td> <a href="/s/smith01.shtml">Smith</a></td>
<td>34</td>
</tr>
</tbody>
</table>
    0    1          2
 0  265  JonesBlue  29
 1  266  Smith      34
    0    1        2
 0  265  jones03  29
 1  266  smith01  34
import BeautifulSoup
import pandas as pd

TABLE = """<table>
<tbody>
<tr>
<td>265</td>
<td <a href="/j/jones03.shtml">Jones</a>Blue</td>
<td >29</td>
</tr>
<tr >
<td>266</td>
<td <a href="/s/smith01.shtml">Smith</a></td>
<td>34</td>
</tr>
</tbody>
</table>"""

table = BeautifulSoup.BeautifulSoup(TABLE)
records = []
for tr in table.findAll("tr"):
    trs = tr.findAll("td")
    record = []
    record.append(trs[0].text)
    record.append(trs[1].a["href"])
    record.append(trs[2].text)
    records.append(record)

df = pd.DataFrame(data=records)
df
我需要将信息保存在
标记中,因为唯一标识符存储在链接中。也就是说,该表应如下所示:

<table>
<tbody>
<tr>
<td>265</td>
<td> <a href="/j/jones03.shtml">Jones</a>Blue</td>
<td>29</td>
</tr>
<tr >
<td>266</td>
<td> <a href="/s/smith01.shtml">Smith</a></td>
<td>34</td>
</tr>
</tbody>
</table>
    0    1          2
 0  265  JonesBlue  29
 1  266  Smith      34
    0    1        2
 0  265  jones03  29
 1  266  smith01  34
import BeautifulSoup
import pandas as pd

TABLE = """<table>
<tbody>
<tr>
<td>265</td>
<td <a href="/j/jones03.shtml">Jones</a>Blue</td>
<td >29</td>
</tr>
<tr >
<td>266</td>
<td <a href="/s/smith01.shtml">Smith</a></td>
<td>34</td>
</tr>
</tbody>
</table>"""

table = BeautifulSoup.BeautifulSoup(TABLE)
records = []
for tr in table.findAll("tr"):
    trs = tr.findAll("td")
    record = []
    record.append(trs[0].text)
    record.append(trs[1].a["href"])
    record.append(trs[2].text)
    records.append(record)

df = pd.DataFrame(data=records)
df
我对各种其他输出都很满意(例如,
jones03 Jones
会更有帮助),但唯一的ID是关键

其他单元格中也有html标记,通常我不希望保存这些标记,但如果这是获取uid的唯一方法,我可以保留这些标记,并在以后清理它们,如果必须的话


有没有一种访问此信息的简单方法?

您可以像下面这样手动解析表:

<table>
<tbody>
<tr>
<td>265</td>
<td> <a href="/j/jones03.shtml">Jones</a>Blue</td>
<td>29</td>
</tr>
<tr >
<td>266</td>
<td> <a href="/s/smith01.shtml">Smith</a></td>
<td>34</td>
</tr>
</tbody>
</table>
    0    1          2
 0  265  JonesBlue  29
 1  266  Smith      34
    0    1        2
 0  265  jones03  29
 1  266  smith01  34
import BeautifulSoup
import pandas as pd

TABLE = """<table>
<tbody>
<tr>
<td>265</td>
<td <a href="/j/jones03.shtml">Jones</a>Blue</td>
<td >29</td>
</tr>
<tr >
<td>266</td>
<td <a href="/s/smith01.shtml">Smith</a></td>
<td>34</td>
</tr>
</tbody>
</table>"""

table = BeautifulSoup.BeautifulSoup(TABLE)
records = []
for tr in table.findAll("tr"):
    trs = tr.findAll("td")
    record = []
    record.append(trs[0].text)
    record.append(trs[1].a["href"])
    record.append(trs[2].text)
    records.append(record)

df = pd.DataFrame(data=records)
df

因为此解析作业需要同时提取文本和属性 值,则不能完全通过诸如
pd.read\u html
。有些必须手工完成

使用,可以使用XPath提取属性值:

import lxml.html as LH
import pandas as pd

content = '''
<table>
<tbody>
<tr>
<td>265</td>
<td> <a href="/j/jones03.shtml">Jones</a>Blue</td>
<td >29</td>
</tr>
<tr >
<td>266</td>
<td> <a href="/s/smith01.shtml">Smith</a></td>
<td>34</td>
</tr>
</tbody>
</table>'''

table = LH.fromstring(content)
for df in pd.read_html(content):
    df['refname'] = table.xpath('//tr/td/a/@href')
    df['refname'] = df['refname'].str.extract(r'([^./]+)[.]')
    print(df)

以上内容可能很有用,因为它只需要几个步骤 添加
refname
列的额外代码行

但是
LH.fromstring
pd.read\uhtml
都解析html。 因此,可以通过删除
pd.read\uhtml
和 使用
LH.fromstring
分析表一次:

table = LH.fromstring(content)
# extract the text from `<td>` tags
data = [[elt.text_content() for elt in tr.xpath('td')] 
        for tr in table.xpath('//tr')]
df = pd.DataFrame(data, columns=['id', 'name', 'val'])
for col in ('id', 'val'):
    df[col] = df[col].astype(int)
# extract the href attribute values
df['refname'] = table.xpath('//tr/td/a/@href')
df['refname'] = df['refname'].str.extract(r'([^./]+)[.]')
print(df)

您可以先使用正则表达式修改文本并删除html标记:

import re, pandas as pd
tbl = """<table>
<tbody>
<tr>
<td>265</td>
<td> <a href="/j/jones03.shtml">Jones</a>Blue</td>
<td>29</td>
</tr>
<tr >
<td>266</td>
<td> <a href="/s/smith01.shtml">Smith</a></td>
<td>34</td>
</tr>
</tbody>
</table>"""
tbl = re.sub('<a.*?href="(.*?)">(.*?)</a>', '\\1 \\2', tbl)
pd.read_html(tbl)

谢谢你的建议。表格相当大,每行有许多单元格,因此如果可能的话,我宁愿避免手动提升(这很难概括),但如果没有更简单的解决方案,我会回到这个问题上来。谢谢。这种精确的方法在我的例子中不起作用,因为其他单元格也有href标记,由xpath拾取;但考虑到无论如何我都必须执行额外的步骤,我使用正则表达式提取UID,然后用它填充新列。很高兴你解决了这个问题!不过要小心;它在许多情况下可能有效,但很难让人理解。在本例中,我并没有真正解析html,只是在指示uid的完整URL中查找文本。它比我喜欢的更脆弱,但这些表应该有一个一致的结构,使它相对安全。