【问题标题】:Python/lxml/Xpath: How do I find the row containing certain text?Python/lxml/Xpath:如何找到包含某些文本的行?
【发布时间】:2012-11-29 07:16:03
【问题描述】:

给定 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 根植于您的解决方案。为了将来有相同问题的开发人员的利益,我在这里发布了一个对我有用的快速而肮脏的脚本:

    #!/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

【问题讨论】:

    标签: python xpath python-2.7 lxml


    【解决方案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'])] 
    

    【讨论】:

    • +10 命令:doc.xpath(u'.//th[div[text()="Cash & Short Term Investments"]]/following-sibling::td/text( )')
    【解决方案2】:

    让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.在 Firefox 中安装 xpath cheker 或 firefinder 以帮助您使用 xpath

    【讨论】:

      猜你喜欢
      • 2018-02-27
      • 2015-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-03
      • 1970-01-01
      • 1970-01-01
      • 2011-09-12
      相关资源
      最近更新 更多