将html数据解析成python列表进行操作
Posted
技术标签:
【中文标题】将html数据解析成python列表进行操作【英文标题】:Parsing html data into python list for manipulation 【发布时间】:2013-07-16 13:16:44 【问题描述】:我正在尝试阅读 html 网站并提取其数据。例如,我想阅读过去 5 年公司的 EPS(每股收益)。基本上,我可以阅读它并且可以使用 BeautifulSoup 或 html2text 来创建一个巨大的文本块。然后我想搜索该文件——我一直在使用 re.search——但似乎无法让它正常工作。这是我要访问的行:
EPS(基本)\n13.4620.6226.6930.1732.81\n\n
所以我想创建一个名为 EPS = [13.46, 20.62, 26.69, 30.17, 32.81] 的列表。
感谢您的帮助。
from stripogram import html2text
from urllib import urlopen
import re
from BeautifulSoup import BeautifulSoup
ticker_symbol = 'goog'
url = 'http://www.marketwatch.com/investing/stock/'
full_url = url + ticker_symbol + '/financials' #build url
text_soup = BeautifulSoup(urlopen(full_url).read()) #read in
text_parts = text_soup.findAll(text=True)
text = ''.join(text_parts)
eps = re.search("EPS\s+(\d+)", text)
if eps is not None:
print eps.group(1)
【问题讨论】:
我soup.prettify()后的html是: EPS (Basic)使用正则表达式解析 html 不是一个好习惯。使用BeautifulSoup
解析器:找到包含rowTitle
类和EPS (Basic)
文本的单元格,然后使用valueCell
类遍历下一个兄弟:
from urllib import urlopen
from BeautifulSoup import BeautifulSoup
url = 'http://www.marketwatch.com/investing/stock/goog/financials'
text_soup = BeautifulSoup(urlopen(url).read()) #read in
titles = text_soup.findAll('td', 'class': 'rowTitle')
for title in titles:
if 'EPS (Basic)' in title.text:
print [td.text for td in title.findNextSiblings(attrs='class': 'valueCell') if td.text]
打印:
['13.46', '20.62', '26.69', '30.17', '32.81']
希望对您有所帮助。
【讨论】:
这是一个非常好的和简单的解决方案。但是当我运行它时,我会在输出中得到一个额外的 u 字符:[u'13.46', u'20.62', u'26.69', u'30.17', u'32.81'] 有什么想法吗?【参考方案2】:我会采取非常不同的方法。我们使用 LXML 来抓取 html 页面
我们切换的原因之一是因为 BS 有一段时间没有维护 - 或者我应该说更新了。
在我的测试中,我运行了以下内容
import requests
from lxml import html
from collections import OrderedDict
page_as_string = requests.get('http://www.marketwatch.com/investing/stock/goog/financials').content
tree = html.fromstring(page_as_string)
现在我查看了页面,我看到数据分为两个表。既然你想要 EPS,我注意到它在第二个表中。我们可以编写一些代码以编程方式解决这个问题,但我会留给你。
tables = [ e for e in tree.iter() if e.tag == 'table']
eps_table = tables[-1]
现在我注意到第一行有列标题,所以我想分隔所有行
table_rows = [ e for e in eps_table.iter() if e.tag == 'tr']
现在让我们获取列标题:
column_headings =[ e.text_content() for e in table_rows[0].iter() if e.tag == 'th']
最后我们可以将列标题映射到行标签和单元格值
my_results = []
for row in table_rows[1:]:
cell_content = [ e.text_content() for e in row.iter() if e.tag == 'td']
temp_dict = OrderedDict()
for numb, cell in enumerate(cell_content):
if numb == 0:
temp_dict['row_label'] = cell.strip()
else:
dict_key = column_headings[numb]
temp_dict[dict_key] = cell
my_results.append(temp_dict)
现在访问结果
for row_dict in my_results:
if row_dict['row_label'] == 'EPS (Basic)':
for key in row_dict:
print key, ':', row_dict[key]
row_label : EPS (Basic)
2008 : 13.46
2009 : 20.62
2010 : 26.69
2011 : 30.17
2012 : 32.81
5-year trend :
现在还有很多事情要做,例如我没有测试正方形(每行中的单元格数量相等)。
最后,我是一个新手,我怀疑其他人会建议使用更直接的方法来获取这些元素(xPath 或 cssselect),但这确实有效,并且它以一种结构良好的方式从表格中获取所有内容。
我应该补充一点,表中的每一行都是可用的,它们是原始行顺序。 my_results 列表中的第一项(即字典)包含第一行的数据,第二项包含第二行的数据,依此类推。
当我需要新版本的 lxml 时,我会访问一个由 UC-IRVINE 非常好的人维护的页面
希望对你有帮助
【讨论】:
【参考方案3】:from bs4 import BeautifulSoup
import urllib2
import lxml
import pandas as pd
url = 'http://markets.ft.com/research/Markets/Tearsheets/Financials?s=CLLN:LSE&subview=BalanceSheet'
soup = BeautifulSoup(urllib2.urlopen(url).read())
table = soup.find('table', 'data-ajax-content' : 'true')
data = []
for row in table.findAll('tr'):
cells = row.findAll('td')
cols = [ele.text.strip() for ele in cells]
data.append([ele for ele in cols if ele])
df = pd.DataFrame(data)
print df
dictframe = df.to_dict()
print dictframe
上面的代码会给你一个来自网页的DataFrame,然后用它来创建一个python字典。
【讨论】:
以上是关于将html数据解析成python列表进行操作的主要内容,如果未能解决你的问题,请参考以下文章