python - 使用 lxml 解析表中的 HTML 数据
问题描述
我仍然是编码的学习者,我的一个朋友告诉我使用 BeautifulSoup。遇到一些问题后 - 我认为我应该使用 lxml 而不是 BeautifulSoup 因为它更好。我希望有人能给我提示如何抓取我正在寻找的文本。我想要的是在“一般信息”字段中找到一个包含以下行和数据的表格。
顺便提一句; 我也尝试使用 pandas 获取表格的元素,但是 - 同时 Pandas 真的很棒,它在每种情况下都没有帮助。我认为我必须刮一些表格元素,我不希望整个表格都是我的 HTML 表格的结构:
<table border="" width="100%">
<tbody><tr valign="top"><td width="50%">
<h3 align="center">item 1</h3>
<ul>
<li><a href="/link.html">name <b>mike/b></a><b>
</b>
<hr width="50%">
</li><li><a href="/link.html">name <b>john</b></a>,
<a href="link.html">name</a>fred</li></ul>
</td><td>
<h3 align="center"> General Information </h3><p></p><ul>
<li>Type of company
</li><li>foundet <a href="/calendar/dayoffoundation.html">10 December</a> <a href="/foundet.html">1900</a>
</li><li> category 1
</li><li> category 2
</li><li>Country: <a href="/country/california.html">california</a></li><li>
</li><li> Town: <a href="/country/sggf.html">san francisco</a>
</li><li>Official Web Site: <a href="https://www.demo-company.net/">https://www.demo-company/</a>
</li><li>Mailing Address:
</li><li>Telephone: 3453455
</li><li>Fax: 433532
</li></ul></td></tr></tbody></table>
其中 td 代表“表数据”,即数据以文本形式存储的位置。
如何使用 lxml 抓取网站并获得以下结果?
[['General Information' 'foundet', 'category1', 'category2', 'country', '等等'] 注意:页面上的所有其他内容都不是必需的!
我通常使用非常有用的模式,所以我们剩下要做的就是使用 BeautifulSoup 选择正确的元素。首先要做的是找到桌子。
我通常使用 find_all() 方法返回满足我们传递给它的要求的所有元素的列表。然后我们必须在该列表中选择我们需要的表:
table = soup.find_all('table')[xy - here a number]
解决方案
您可以lxml
使用bs4
. 只需添加nth-child/nth-of-type
到目标 right td
,然后向下获取 theh3
和 the li
(还有其他方法,例如相邻兄弟组合):
from bs4 import BeautifulSoup
html = '''
<table border="" width="100%">
<tbody><tr valign="top"><td width="50%">
<h3 align="center">item 1</h3>
<ul>
<li><a href="/link.html">name <b>mike/b></a><b>
</b>
<hr width="50%">
</li><li><a href="/link.html">name <b>john</b></a>,
<a href="link.html">name</a>fred</li></ul>
</td><td>
<h3 align="center"> General Information </h3><p></p><ul>
<li>Type of company
</li><li>foundet <a href="/calendar/dayoffoundation.html">10 December</a> <a href="/foundet.html">1900</a>
</li><li> category 1
</li><li> category 2
</li><li>Country: <a href="/country/california.html">california</a></li><li>
</li><li> Town: <a href="/country/sggf.html">san francisco</a>
</li><li>Official Web Site: <a href="https://www.demo-company.net/">https://www.demo-company/</a>
</li><li>Mailing Address:
</li><li>Telephone: 3453455
</li><li>Fax: 433532
</li></ul></td></tr></tbody></table>
'''
soup = bs(html, 'lxml')
print([i.text.strip() for i in soup.select('td:nth-child(2) > h3, td:nth-child(2) > ul > li')])
如果您事先知道标题(您似乎知道),您可以使用更有针对性的方法:contains
(最新版本中的:-soup-contains ):
from bs4 import BeautifulSoup
import pandas as pd
html = '''
<table border="" width="100%">
<tbody><tr valign="top"><td width="50%">
<h3 align="center">item 1</h3>
<ul>
<li><a href="/link.html">name <b>mike/b></a><b>
</b>
<hr width="50%">
</li><li><a href="/link.html">name <b>john</b></a>,
<a href="link.html">name</a>fred</li></ul>
</td><td>
<h3 align="center"> General Information </h3><p></p><ul>
<li>Type of company
</li><li>foundet <a href="/calendar/dayoffoundation.html">10 December</a> <a href="/foundet.html">1900</a>
</li><li> category 1
</li><li> category 2
</li><li>Country: <a href="/country/california.html">california</a></li><li>
</li><li> Town: <a href="/country/sggf.html">san francisco</a>
</li><li>Official Web Site: <a href="https://www.demo-company.net/">https://www.demo-company/</a>
</li><li>Mailing Address:
</li><li>Telephone: 3453455
</li><li>Fax: 433532
</li></ul></td></tr></tbody></table>
'''
soup = bs(html, 'lxml')
df = pd.DataFrame(
[i.text.strip() for i in soup.select('td:has(h3:contains("General Information")) > ul > li')]
,columns = ['General Information']
)
print(df)
推荐阅读
- java - QuickFIX - 接收和发送来自不同算法的订单(来源)
- c# - Same project in two solutions throwing System.MissingMethodException in only one of the solutions
- javascript - 从 Cloud Firestore 中提取时,时间戳以字符串形式出现
- java - 为什么代码使用较小的列表实例化哈希集?
- visual-studio - 是否可以在 Visual Studio 2019 中选择一段代码并将其保存为单独的文件?
- python - 如何修复 python socket-io 服务器中的“Access-Control-Allow-Origin”错误
- file - Tcl如何使用文件属性命令改变权限?
- java - Android Studio - java.lang.NullPointerException: storage == null
- ios - iOS UI 测试 - UILabel *with* accessibilityIdentifier 找不到
- odoo - 我们如何在 `purchase.order.line` 上打开 `seller_ids` 视图