HTML table 到 pandas table:html 标签内的信息
HTML table to pandas table: Info inside html tags
我有一个来自网络的大型 table,通过请求访问并使用 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>
当我使用 pd.read_html(tbl)
将其转换为 pandas 时,输出如下所示:
0 1 2
0 265 JonesBlue 29
1 266 Smith 34
我需要将信息保存在 <A HREF ... >
标签中,因为唯一标识符存储在 link 中。也就是说,table 应该是这样的:
0 1 2
0 265 jones03 29
1 266 smith01 34
我对其他各种输出没意见(例如,jones03 Jones
会更有帮助),但唯一 ID 很重要。
其他单元格中也有 html 标签,通常我不希望保存这些标签,但如果这是获取 uid 的唯一方法,我可以保留这些标签并且如果必须的话,稍后再清理它们。
是否有访问此信息的简单方法?
您可以像这样简单地手动解析 table:
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
这给了你
0 1 2
0 265 /j/jones03.shtml 29
1 266 /s/smith01.shtml 34
由于此解析作业需要提取文本和属性
值,它不能完全 "out-of-the-box" 通过这样的函数来完成
pd.read_html
。其中一些必须手工完成。
使用 lxml,您可以使用 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)
产量
0 1 2 refname
0 265 JonesBlue 29 jones03
1 266 Smith 34 smith01
以上可能有用,因为它只需要几个
添加 refname
列的额外代码行。
但是 LH.fromstring
和 pd.read_html
都解析 HTML。
所以它的效率可以通过删除 pd.read_html
和
用 LH.fromstring
:
解析一次 table
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)
产量
id name val refname
0 265 JonesBlue 29 jones03
1 266 Smith 34 smith01
您可以先使用正则表达式修改文本并删除 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)
这给了你
[ 0 1 2
0 265 /j/jones03.shtml JonesBlue 29
1 266 /s/smith01.shtml Smith 34]
我有一个来自网络的大型 table,通过请求访问并使用 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>
当我使用 pd.read_html(tbl)
将其转换为 pandas 时,输出如下所示:
0 1 2
0 265 JonesBlue 29
1 266 Smith 34
我需要将信息保存在 <A HREF ... >
标签中,因为唯一标识符存储在 link 中。也就是说,table 应该是这样的:
0 1 2
0 265 jones03 29
1 266 smith01 34
我对其他各种输出没意见(例如,jones03 Jones
会更有帮助),但唯一 ID 很重要。
其他单元格中也有 html 标签,通常我不希望保存这些标签,但如果这是获取 uid 的唯一方法,我可以保留这些标签并且如果必须的话,稍后再清理它们。
是否有访问此信息的简单方法?
您可以像这样简单地手动解析 table:
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
这给了你
0 1 2
0 265 /j/jones03.shtml 29
1 266 /s/smith01.shtml 34
由于此解析作业需要提取文本和属性
值,它不能完全 "out-of-the-box" 通过这样的函数来完成
pd.read_html
。其中一些必须手工完成。
使用 lxml,您可以使用 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)
产量
0 1 2 refname
0 265 JonesBlue 29 jones03
1 266 Smith 34 smith01
以上可能有用,因为它只需要几个
添加 refname
列的额外代码行。
但是 LH.fromstring
和 pd.read_html
都解析 HTML。
所以它的效率可以通过删除 pd.read_html
和
用 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)
产量
id name val refname
0 265 JonesBlue 29 jones03
1 266 Smith 34 smith01
您可以先使用正则表达式修改文本并删除 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)
这给了你
[ 0 1 2
0 265 /j/jones03.shtml JonesBlue 29
1 266 /s/smith01.shtml Smith 34]