【问题标题】:Python/lxml web scraping: dealing with blank entriesPython/lxml 网页抓取:处理空白条目
【发布时间】:2013-04-25 00:25:03
【问题描述】:

我正在使用 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”)?我愿意处理这些不需要的标签,因为它们很容易删除。

【问题讨论】:

  • 不是答案,但你一定要看看Scrapy

标签: python xpath lxml


【解决方案1】:

不要显式匹配文本节点——只获取节点的文本值:

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 上下文。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-10
    • 1970-01-01
    • 1970-01-01
    • 2016-02-02
    • 1970-01-01
    相关资源
    最近更新 更多