Python / lxml / Xpath:如何找到包含特定文本的行?

时间:2012-11-29 07:16:03

标签: python xpath python-2.7 lxml

鉴于URL http://www.smartmoney.com/quote/FAST/?story=financials&timewindow=1&opt=YB&isFinprint=1&framework.view=smi_emptyView,您将如何捕获和打印整行数据的内容?

例如,如何获得类似于以下内容的输出: “现金和短期投资144,841 169,760 189,252 86,743 57,379”?或者类似“物业,工厂和设备 - 总收入725,104 632,332 571,467 538,805 465,493”?

我已经通过网站http://www.techchorus.net/web-scraping-lxml介绍了Xpath的基础知识。但是,Xpath语法对我来说仍然是一个谜。

我已经在BeautifulSoup中成功完成了这项工作。我喜欢BeautifulSoup不要求我知道文件结构的事实 - 它只是查找包含我搜索的文本的元素。不幸的是,BeautifulSoup对于一个必须要做到这么多次的脚本来说太慢了。我在BeautifulSoup中的任务的源代码是(title_input等于“现金和短期投资”):

    page = urllib2.urlopen (url_local)
    soup = BeautifulSoup (page)
    soup_line_item = soup.findAll(text=title_input)[0].parent.parent.parent
    list_output = soup_line_item.findAll('td') # List of elements

那么lxml中的等效代码是什么?

编辑1:我第一次发布时隐藏了网址。我现在已经解决了这个问题。

编辑2:我添加了基于BeautifulSoup的解决方案,以澄清我正在尝试做的事情。

编辑3:+10到root用于您的解决方案。为了有同样问题的未来开发人员的利益,我在这里发布一个快速而肮脏的脚本,对我有用:

    #!/usr/bin/env python
    import urllib
    import lxml.html

    url = 'balancesheet.html'

    result = urllib.urlopen(url)
    html = result.read()


    doc = lxml.html.document_fromstring(html)
    x = doc.xpath(u'.//th[div[text()="Cash & Short Term Investments"]]/following-sibling::td/text()')
    print x

2 个答案:

答案 0 :(得分:1)

In [18]: doc.xpath(u'.//th[div[text()="Cash & Short Term Investments"]]/following-sibling::td/text()')
Out[18]: ['   144,841', '   169,760', '   189,252', '    86,743', '    57,379']

或者您可以定义一个小函数来按文本获取行:

In [19]: def func(doc,txt):
    ...:     exp=u'.//th[div[text()="{0}"]]'\
    ...:         u'/following-sibling::td/text()'.format(txt)
    ...:     return [i.strip() for i in doc.xpath(exp)]

In [20]: func(doc,u'Total Accounts Receivable')
Out[20]: ['338,594', '270,133', '214,169', '244,940', '236,331']

或者您可以将所有行转到dict

In [21]: d={}

In [22]: for i in doc.xpath(u'.//tbody/tr'):
    ...:     if len(i.xpath(u'.//th/div/text()')):
    ...:         d[i.xpath(u'.//th/div/text()')[0]]=\
    ...:         [e.strip() for e in i.xpath(u'.//td/text()')]

In [23]: d.items()[:3]
Out[23]: 
[('Accounts Receivables, Gross',
     ['344,241', '274,894', '218,255', '247,600', '238,596']),
 ('Short-Term Investments', 
     ['27,165', '26,067', '24,400', '851', '159']),
 ('Cash & Short Term Investments',
     ['144,841', '169,760', '189,252', '86,743', '57,379'])] 

答案 1 :(得分:0)

让html保存html源代码:

import lxm.html
doc = lxml.html.document_fromstring(html)
rows_element = doc.xpath('/html/body/div/div[2]/div/div[5]/div/div/table/tbody/tr')
for row in rows_element:
     print row.text_content()

未经测试但应该正常工作

P.S.Install xpath cheker或firefox中的firefinder帮你解决xpath