【问题标题】:Extracting date and other data from scraped items从抓取的项目中提取日期和其他数据
【发布时间】:2016-07-24 18:25:33
【问题描述】:

我正在编写一个 Python 代码,使用 lxml、urllib 和 csv 来抓取 a Brazil government site 中的语音。

我能够使用 XPath 找到每个演讲的标题和链接,但不是确切的日期,因为之前没有特定的标签来表示演讲的日期。

当我使用 XPath '//span[@class="summary-view-icon"]/text() 时,刮板会带回日期、小时和单词“Página”(页面,葡萄牙语)。我知道这个 Xpath 不对,但我不知道如何只选择日期。

即使出现这个错误,我也能够将 抓取的 内容转换为列表并进行编辑以删除除日期之外的所有内容。问题在于,如下所示,最终列表中还有一些我无法删除的字符。

这里似乎有两种解决方案:正确设置 XPath 或编辑列表中的其他字符。我该怎么做?

['\n 18/12/2015\n ', '\n 21/12/2015\n ', '\n 21/12/2015\n ', '\n 22/12/2015\n ', '\n 22/12/2015\n ', '\n 22/12/2015\n ', '\n 11/01/2016\n ', '\n 19/01/2016\n ', '\n 21/01/2016\n ', '\n 26/01/2016\n ', '\n 27/01/2016\n ', '\n 27/01/2016\n ', '\n 28/01/2016\n ', '\n 01/ 02/2016\n ', '\n 01/02/2016\n ', '\n 02/02/2016\n ', '\n 02/02/2016\n ', '\n 02/02/ 2016\n ', '\n 03/02/2016\n ', '\n 03/02/2016\n ', '\n 19/02/2016\n ', '\n 19/02/2016\n ', '\n 22/ 02/2016\n ', '\n 26/02/2016\n ', '\n 26/02/2016\n ', '\n 02/03/2016\n ', '\n 03/03/ 2016\n ', '\n 04/03/2016\n ', '\n 07/03/2016\n ', '\n 04/02/2016\n ', '\n 08/03/2016\n ', '\n 09/ 03/2016\n ', '\n 17/03/2016\n ', '\n 18/03/2016\n ', '\n 22/03/2016\n ', '\n 23/03/ 2016\n ', '\n 23/03/2016\n ', '\n 30/03/2016\n ', '\n 31/03/2016\n ', '\n 01/04/2016\n ']

【问题讨论】:

  • 去掉[d.strip() for d in ds]周围的空格

标签: python algorithm xpath web-scraping lxml


【解决方案1】:

这会让你得到你想要的:

items = response.xpath('//div[@id="content-core"]//div[contains(@class, "tileItem")]')
for item in items:
    date = item.xpath('normalize-space(.//span[@class="summary-view-icon"][i[@class="icon-day"] ]//text()[normalize-space()])')

使用 normalize-space 两次将删除删除空结果+删除最终结果的所有空格。

【讨论】:

    【解决方案2】:

    尝试使用以下 XPath 将结果缩小到仅日期:

    //span[@class="summary-view-icon"][i/@class="icon-day"]/text()[normalize-space()]
    

    上述 XPath 的最后一位 (text()[normalize-space()]) 仅返回 非空 文本节点。从这里开始,您仍然需要使用 strip() 删除不必要的空格:

    query = '//span[@class="summary-view-icon"][i/@class="icon-day"]/text()[normalize-space()]'
    dates = root.xpath(query)
    result = [date.strip() for date in dates]
    

    【讨论】:

      【解决方案3】:

      您可以使用strip 从列表中的元素中删除所有换行符/空格:

      new_list = [item.strip() for item in old_list]
      

      编辑:您说您可以将结果转换为问题中的列表,在这种情况下,您可以去除那里的元素。

      【讨论】:

        【解决方案4】:

        这里使用regular expression

        dates = [re.search(r'\d{2}/\d{2}/\d{4}', item, re.MULTILINE).group(0) for item in old_list]
        

        给予:

        ['18/12/2015', '21/12/2015', '21/12/2015', '22/12/2015', '22/12/2015',
        '22/12/2015', '11/01/2016', '19/01/2016', '21/01/2016', '26/01/2016',
        '27/01/2016', '27/01/2016', '28/01/2016', '01/02/2016', '01/02/2016',
        '02/02/2016', '02/02/2016', '02/02/2016', '03/02/2016', '03/02/2016',
        '19/02/2016', '19/02/2016', '22/02/2016', '26/02/2016', '26/02/2016',
        '02/03/2016', '03/03/2016', '04/03/2016', '07/03/2016', '04/02/2016',
        '08/03/2016', '09/03/2016', '17/03/2016', '18/03/2016', '22/03/2016',
        '23/03/2016', '23/03/2016', '30/03/2016', '31/03/2016', '01/04/2016']
        

        这有助于处理具有更多差异或意外格式的数据。

        【讨论】:

          【解决方案5】:

          您可以使用正则表达式以您想要的格式提取日期,而无需额外的字符。

          基于页面结构,我开发了一个 scraper 使用 re 来演示我将如何做到这一点:

          import requests, re
          from lxml import etree
          
          
          def get_speeach_data(item):
              title = item.xpath('.//h2[@class="tileHeadline"]/a/text()')[0]
              
              sidebar = item.xpath('./span[@class="documentByLine"]')[0]
              sidebar_html = etree.tostring( sidebar )
              
              m = re.search(r'(\d+/\d+/\d+)', sidebar_html)
              date = m.group(1)
              
              m = re.search(r'(\d+h\d+)', sidebar_html)
              hour = m.group(1)
              
              return { 'title' : title, 'date' : date, 'hour' : hour }
              
          
          
          if __name__ == '__main__':
              url = 'http://www2.planalto.gov.br/acompanhe-o-planalto/discursos/discursos-da-presidenta?b_start:int=0'
              
              r = requests.get( url )
              
              if r.status_code == 200:
                  page = etree.HTML( r.content )
                  
                  raw_speeaches = page.xpath('//*[@id="content-core"]/div')
                  speeaches = map(get_speeach_data, raw_speeaches)
                  print speeaches
          

          【讨论】:

          • 太棒了!感谢您的帮助
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-07-05
          • 2021-05-30
          • 2021-07-07
          • 1970-01-01
          • 1970-01-01
          • 2015-04-01
          • 1970-01-01
          相关资源
          最近更新 更多