Python/lxml web抓取:处理空白条目

Python/lxml web抓取:处理空白条目,python,xpath,lxml,Python,Xpath,Lxml,我正在使用Python和lxml从彭博网站上搜集ETF和共同基金的数据。我试图从中提取数据的一个页面示例是 对于每个基金,我需要符号、名称、基金类型和目标。我在清除符号、名称或基金类型方面没有问题。然而,我对目标有困难。你会在我引用的网页(以及随后的网页)上看到目标是空的。页面上最后一笔基金的HTML如下所示: <tr class='tkr_alt'> <td class="name"> <a href="/quote/ADTKEX:US"&

我正在使用Python和lxml从彭博网站上搜集ETF和共同基金的数据。我试图从中提取数据的一个页面示例是

对于每个基金,我需要符号、名称、基金类型和目标。我在清除符号、名称或基金类型方面没有问题。然而,我对目标有困难。你会在我引用的网页(以及随后的网页)上看到目标是空的。页面上最后一笔基金的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>
此代码将基金目标复制到数组中。不幸的是,代码完全忽略了条目丢失的事实。因此,名称、符号和基金类型的列表都将有X个元素,但目标的列表将只有X-1个元素

如何让脚本识别空白条目并提供nIL或‘’?< /P>的数组元素?


是否有一种方法可以捕获整个列条目(看起来像“blahblahblah”)?我愿意处理这些不需要的标记,因为它们很容易删除。

不明确匹配文本节点——只需获取节点的文本值:

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

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

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

不是答案,但您肯定应该签出。不是答案,但您肯定应该签出。