用漂亮的汤和熊猫刮桌子时如何保留链接
Posted
技术标签:
【中文标题】用漂亮的汤和熊猫刮桌子时如何保留链接【英文标题】:how to preserve links when scraping a table with beautiful soup and pandas 【发布时间】:2017-07-06 05:47:15 【问题描述】:使用Beautiful soup
和Pandas
抓取网页以获取表格。其中一列有一些网址。当我将 html 传递给 pandas 时,href
丢失了。
有没有办法只保留该列的 url 链接?
示例数据(经过编辑以更好地适用于案例):
<html>
<body>
<table>
<tr>
<td>customer</td>
<td>country</td>
<td>area</td>
<td>website link</td>
</tr>
<tr>
<td>IBM</td>
<td>USA</td>
<td>EMEA</td>
<td><a href="http://www.ibm.com">IBM site</a></td>
</tr>
<tr>
<td>CISCO</td>
<td>USA</td>
<td>EMEA</td>
<td><a href="http://www.cisco.com">cisco site</a></td>
</tr>
<tr>
<td>unknown company</td>
<td>USA</td>
<td>EMEA</td>
<td></td>
</tr>
</table>
</body>
</html>
我的python代码:
file = open(url,"r")
soup = BeautifulSoup(file, 'lxml')
parsed_table = soup.find_all('table')[1]
df = pd.read_html(str(parsed_table),encoding='utf-8')[0]
df
输出(导出为 CSV):
customer;country;area;website
IBM;USA;EMEA;IBM site
CISCO;USA;EMEA;cisco site
unknown company;USA;EMEA;
df 输出正常,但链接丢失。我需要保留链接。至少是 URL。
有什么提示吗?
【问题讨论】:
【参考方案1】:pd.read_html
假定您感兴趣的数据在文本中,而不是标签属性中。但是,自己刮桌子并不难:
import bs4 as bs
import pandas as pd
with open(url,"r") as f:
soup = bs.BeautifulSoup(f, 'lxml')
parsed_table = soup.find_all('table')[1]
data = [[td.a['href'] if td.find('a') else
''.join(td.stripped_strings)
for td in row.find_all('td')]
for row in parsed_table.find_all('tr')]
df = pd.DataFrame(data[1:], columns=data[0])
print(df)
产量
customer country area website link
0 IBM USA EMEA http://www.ibm.com
1 CISCO USA EMEA http://www.cisco.com
2 unknown company USA EMEA
【讨论】:
KeyError: 'href' ,似乎并非所有行都有链接 unutbu ""tag[key] 返回标签的 'key' 属性的值,如果不存在则抛出异常。""" 如果使用合并单元格,如 col span 或 row span > 1,则不起作用【参考方案2】:这样检查标签是否存在:
import numpy as np
with open(url,"r") as f:
sp = bs.BeautifulSoup(f, 'lxml')
tb = sp.find_all('table')[56]
df = pd.read_html(str(tb),encoding='utf-8', header=0)[0]
df['href'] = [np.where(tag.has_attr('href'),tag.get('href'),"no link") for tag in tb.find_all('a')]
【讨论】:
【参考方案3】:如果您要从 html 表中获取多个链接,这是另一种方法。我宁愿使用单独的 for 循环而不是进行列表理解,这样代码对于那些不熟悉 python 的人来说更具可读性,并且如果出现错误,更容易调整代码或处理错误。我希望它会对某人有所帮助。
soup = BeautifulSoup(html, "lxml")
table = table.find('table')
thead = table.find('thead')
column_names = [th.text.strip() for th in thead.find_all('th')]
data = []
for row in table.find_all('tr'):
row_data = []
for td in row.find_all('td'):
td_check = td.find('a')
if td_check is not None:
link = td.a['href']
row_data.append(link)
else:
not_link = ''.join(td.stripped_strings)
if not_link == '':
not_link = None
row_data.append(not_link)
data.append(row_data)
df = pd.DataFrame(data[1:], columns=column_names)
df_dict = df.to_dict('records')
for row in df_dict:
print(row)
【讨论】:
如果有多个表使用:table = soup.find_all('table')[1] 其中 [1] 是您感兴趣的表的索引。以上是关于用漂亮的汤和熊猫刮桌子时如何保留链接的主要内容,如果未能解决你的问题,请参考以下文章