我正在使用Python和lxml从Bloomberg网站上获取ETF和共同基金的数据。我试图从中抓取数据的页面示例是http://www.bloomberg.com/markets/funds/country/usa/。
对于每个基金,我需要符号,名称,基金类型和目标。我在抓取符号,名称或基金类型方面没有任何问题。但是,我对目标有困难。您将在我引用的网页(以及后续页面)中看到目标是空白的。页面上最后一个基金的HTML如下所示:
<tr class='tkr_alt'>
<td class="name">
<a href="/quote/ADTKEX:US"><span>Advisor Disciplined Trust 193 - Taxable Municipal Bond Portfolio - Series 1</span> (ADTKEX)</a></td>
<td class="symbol">ADTKEX:US</td>
<td>UIT</td>
<td></td>
</tr>
第一栏有基金名称,第二栏有股票代码,第三栏有基金类型(ETF,UIT,开放式基金,封闭式基金等),第四栏有目标(增长,价值,收入等)。对于这个特定基金,目标不见了。
我用来提取基金目标的代码(最后一栏)是:
result = urllib.urlopen(filename)
element_html = result.read()
doc = lxml.html.document_fromstring (element_html)
list_obj = doc.xpath (u'.//tr[td[contains (@*, "name")]]/following-sibling::td/text()')
此代码将基金目标复制到一个数组中。不幸的是,代码完全忽略了一个条目缺失的事实。因此,名称,符号和基金类型的列表将各自具有X元素,但目标列表将只有X-1元素。
如何让脚本识别空白条目并提供nil或''的数组元素?
有没有办法可以捕获整个列条目(看起来像“blahblahblah”)?我愿意处理这些不需要的标签,因为它们很容易删除。
答案 0 :(得分:4)
显式不匹配文本节点 - 只需获取节点的文本值:
doc.xpath(u'string(.//tr[td[contains (@*, "name")]]/following-sibling::td)')
或者你可以在Python方面做同样的事情:
tds = doc.xpath(u'.//tr[td[contains (@*, "name")]]/following-sibling::td')
etree.tostring(tds[0], method="text")
但是我认为你的做法是错误的。而不是获得四个不同的列表并将它们压缩在一起,找到容器行,然后一次性获取该上下文中的项目。这是一个完整的实现:
from lxml import etree
from collections import namedtuple
Fund = namedtuple('Fund', 'name symbol type objective')
def astext(elem):
"Return stripped text value of element"
return etree.tostring(elem, method='text').strip()
url = 'http://www.bloomberg.com/markets/funds/country/usa/'
xpfundrows = u"//table[@class='ticker_data']/descendant::tr[td[1][@class='name']]"
doc = etree.parse(url, etree.HTMLParser())
funds = []
for row in doc.xpath(xpfundrows):
cells = row.findall('td')
fund = Fund(astext(cell) for cell in cells)
funds.append(fund)
print funds
您可以在内循环中更加谨慎(例如,对每个数据位使用name = row.xpath("td[@class='name']")
等),但基本原理是相同的 - 将搜索锚定到tr
上下文