【问题标题】:Strip \n \t \r in scrapy在scrapy中剥离\n \t \r
【发布时间】:2016-02-09 09:24:59
【问题描述】:

我正在尝试用爬虫蜘蛛去除 \r \n \t 字符,然后制作一个 json 文件。

我有一个充满新行的“描述”对象,但它没有做我想要的:将每个描述与标题匹配。

我尝试使用 map(unicode.strip()) 但它并没有真正起作用。作为scrapy的新手,我不知道是否有另一种更简单的方法或者map unicode是如何工作的。

这是我的代码:

def parse(self, response):
    for sel in response.xpath('//div[@class="d-grid-main"]'):
        item = xItem()
        item['TITLE'] = sel.xpath('xpath').extract()
        item['DESCRIPTION'] = map(unicode.strip, sel.xpath('//p[@class="class-name"]/text()').extract())

我也试过:

item['DESCRIPTION'] = str(sel.xpath('//p[@class="class-name"]/text()').extract()).strip()

但它引发了错误。最好的方法是什么?

【问题讨论】:

  • 您好,“它实际上不起作用”是什么意思? strip() 只考虑前导字符和尾随字符,因此如果您想删除字符串内的任何内容,则需要其他方式。如果这是您的问题,import rere.sub('[\r\n\t]', '', 'Hel\nlo\r!') 会有所帮助。
  • 我建议结帐ItemLoaders doc.scrapy.org/en/latest/topics/loaders.html,它允许您管理Items 的输入和输出
  • QuentinPradet 谢谢,事实上保罗的回答很好,我不知道。还有花岗龙,我会研究的,谢谢

标签: python unicode scrapy


【解决方案1】:

unicode.strip 只处理字符串开头和结尾的空白字符

返回删除前导和尾随字符的字符串副本。

中间没有\n\r\t

您可以使用自定义方法删除字符串中的这些字符(使用正则表达式模块),甚至可以使用XPath's normalize-space()

通过去除前导和尾随空格并用单个空格替换空格字符序列,返回带有空格规范化的参数字符串。

python shell 会话示例:

>>> text='''<html>
... <body>
... <div class="d-grid-main">
... <p class="class-name">
... 
...  This is some text,
...  with some newlines \r
...  and some \t tabs \t too;
... 
... <a href="http://example.com"> and a link too
...  </a>
... 
... I think we're done here
... 
... </p>
... </div>
... </body>
... </html>'''
>>> response = scrapy.Selector(text=text)
>>> response.xpath('//div[@class="d-grid-main"]')
[<Selector xpath='//div[@class="d-grid-main"]' data=u'<div class="d-grid-main">\n<p class="clas'>]
>>> div = response.xpath('//div[@class="d-grid-main"]')[0]
>>> 
>>> # you'll want to use relative XPath expressions, starting with "./"
>>> div.xpath('.//p[@class="class-name"]/text()').extract()
[u'\n\n This is some text,\n with some newlines \r\n and some \t tabs \t too;\n\n',
 u"\n\nI think we're done here\n\n"]
>>> 
>>> # only leading and trailing whitespace is removed by strip()
>>> map(unicode.strip, div.xpath('.//p[@class="class-name"]/text()').extract())
[u'This is some text,\n with some newlines \r\n and some \t tabs \t too;', u"I think we're done here"]
>>> 
>>> # normalize-space() will get you a single string on the whole element
>>> div.xpath('normalize-space(.//p[@class="class-name"])').extract()
[u"This is some text, with some newlines and some tabs too; and a link too I think we're done here"]
>>> 

【讨论】:

  • 我想对整个身体进行规范化空间: response.xpath('.').extract() 这可行,但使用 normalize-space: response.xpath('normalize-space(.)' ).extract() 像 这样的 html 标签被删除了,为什么?
  • @Baks, normalize-space(.) 返回上下文节点的空间标准化string value,它是后代文本节点的串联:"元素节点的字符串值是按文档顺序连接元素节点的所有文本节点后代的字符串值。"
【解决方案2】:

我是一个 python,scrapy 新手,我今天遇到了类似的问题,在以下模块/函数 w3lib.html.replace_escape_chars 的帮助下解决了这个问题我为我的项目加载器创建了一个默认输入处理器,它可以工作没有任何问题,您也可以将它绑定到特定的 scrapy.Field() 上,它的好处是它适用于 css 选择器和 csv 提要导出:

from w3lib.html import replace_escape_chars
yourloader.default_input_processor = MapCompose(relace_escape_chars)

【讨论】:

    【解决方案3】:

    正如保罗 trmbrth 建议的 in his answer

    div.xpath('normalize-space(.//p[@class="class-name"])').extract()
    

    很可能是你想要的。但是,normalize-space 也将字符串中包含的空格压缩为一个空格。如果您只想删除 \r\n\t 而不会干扰其他空格,则可以使用 translate() 删除字符。

    trans_table = {ord(c): None for c in u'\r\n\t'}
    item['DESCRIPTION] = ' '.join(s.translate(trans_table) for s in sel.xpath('//p[@class="class-name"]/text()').extract())
    

    这仍然会留下不在集合\r\n\t 中的前导和尾随空格。如果您也想摆脱它,只需拨打strip()

    item['DESCRIPTION] = ' '.join(s.strip().translate(trans_table) for s in sel.xpath('//p[@class="class-name"]/text()').extract())
    

    【讨论】:

    • 完美。我从来不知道这一点,它在没有正则表达式的情况下解决了我所有的空白问题。
    • div.xpath('normalize-space(.//p[@class="class-name"])').extract() 为我工作,谢谢。
    【解决方案4】:

    从 alibris.com 中提取价格的最简单示例是

    response.xpath('normalize-space(//td[@class="price"]//p)').get()
    

    【讨论】:

      【解决方案5】:

      当我使用scrapy爬取网页时,我遇到了同样的问题。我有两种方法来解决这个问题。首先使用 replace() 函数。 AS“response.xpath”返回一个列表格式,但替换函数只操作字符串格式。所以我使用 for 循环将列表中的每个项目作为字符串获取,替换每个项目中的 '\n''\t',然后追加到新列表。

      import re
      test_string =["\n\t\t", "\n\t\t\n\t\t\n\t\t\t\t\t", "\n", "\n", "\n", "\n", "Do you like shopping?", "\n", "Yes, I\u2019m a shopaholic.", "\n", "What do you usually shop for?", "\n", "I usually shop for clothes. I\u2019m a big fashion fan.", "\n", "Where do you go shopping?", "\n", "At some fashion boutiques in my neighborhood.", "\n", "Are there many shops in your neighborhood?", "\n", "Yes. My area is the city center, so I have many choices of where to shop.", "\n", "Do you spend much money on shopping?", "\n", "Yes and I\u2019m usually broke at the end of the month.", "\n", "\n\n\n", "\n", "\t\t\t\t", "\n\t\t\t\n\t\t\t", "\n\n\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t"]
      print(test_string)
              # remove \t \n    
      a = re.compile(r'(\t)+')     
      b = re.compile(r'(\n)+')
      text = []
      for n in test_string:
          n = a.sub('',n)
          n = b.sub('',n)
          text.append(n)
      print(text)
              # remove all ''
      while '' in text:
          text.remove('')
      print(text)
      

      第二种方法使用map()和strip。map()函数直接处理列表,得到原始格式。python2中使用'Unicode',python3中改为'str',如下:

      text = list(map(str.strip, test_string))
      print(text)
      

      strip函数只删除字符串开头和结尾的\n\t\r,而不是字符串中间。它与remove函数不同。

      【讨论】:

        【解决方案6】:

        如果您想保留列表而不是所有联合字符串,则无需添加额外的步骤,您只需调用getall() 而不是get()

        response.xpath('normalize-space(.//td[@class="price"]/text())').getall()
        

        另外,您应该在末尾添加text()

        希望对大家有帮助!

        【讨论】:

          【解决方案7】:

          你可以尝试使用 css 结合 get().strip(),它对我有用

          【讨论】:

          • 您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-24
          • 1970-01-01
          • 2018-07-25
          • 2014-06-26
          • 2023-04-03
          • 1970-01-01
          相关资源
          最近更新 更多