【问题标题】:Cleaning Text with python and re用python和re清理文本
【发布时间】:2019-03-15 16:55:23
【问题描述】:

我需要清理一些文本,如下面的代码所示:

import re
def clean_text(text):
    text = text.lower()
    #foction de replacement
    text = re.sub(r"i'm","i am",text)
    text = re.sub(r"she's","she is",text)
    text = re.sub(r"can't","cannot",text)
    text = re.sub(r"[-()\"#/@;:<>{}-=~|.?,]","",text)
    return text

clean_questions= []
for question in questions: 
    clean_questions.append(clean_text(question))

并且这段代码必须给我questions 列表干净但我得到干净的questions 为空。我重新打开了spyder,列表已满,但没有被清理,然后重新打开它,我把它弄空了.. 控制台错误说:

In [10] :clean_questions= [] 
   ...: for question in questions: 
   ...: clean_questions.append(clean_text(question))
Traceback (most recent call last):

  File "<ipython-input-6-d1c7ac95a43f>", line 3, in <module>
    clean_questions.append(clean_text(question))

  File "<ipython-input-5-8f5da8f003ac>", line 16, in clean_text
    text = re.sub(r"[-()\"#/@;:<>{}-=~|.?,]","",text)

  File "C:\Users\hp\Anaconda3\lib\re.py", line 192, in sub
    return _compile(pattern, flags).sub(repl, string, count)

  File "C:\Users\hp\Anaconda3\lib\re.py", line 286, in _compile
   p = sre_compile.compile(pattern, flags)

  File "C:\Users\hp\Anaconda3\lib\sre_compile.py", line 764, in compile
    p = sre_parse.parse(p, flags)

  File "C:\Users\hp\Anaconda3\lib\sre_parse.py", line 930, in parse
    p = _parse_sub(source, pattern, flags & SRE_FLAG_VERBOSE, 0)

  File "C:\Users\hp\Anaconda3\lib\sre_parse.py", line 426, in _parse_sub
    not nested and not items))

  File "C:\Users\hp\Anaconda3\lib\sre_parse.py", line 580, in _parse
    raise source.error(msg, len(this) + 1 + len(that))

error: bad character range }-=

我使用的是 Python 3.6,特别是 Anaconda 构建版 Anaconda3-2018.12-Windows-x86_64。

【问题讨论】:

  • 在最后一个模式中转义 \{\}。但您可能需要一个字符类:"[-()\"#/@;:&lt;&gt;{}=~|.?,]+"
  • @AndrasDeak:回溯显示他们正在使用字符类。所以真正的问题是一个 bad 类,而不是缺少一个。
  • @dasertnaut 我是使用 DNLP 创建聊天机器人的第一步
  • @AndrasDeak 我删除了所有句子但没有任何改变
  • 现有的答案应该很好地解释了问题所在;你还不明白吗?顶级问题是}-= 表示字符组(方括号)内的“从}= 在ASCII 表中”。

标签: python regex python-3.x character-class


【解决方案1】:

您的字符类(如回溯中所示)无效; } 在序数值中位于 = 之后(} 是 125,= 是 61),它们之间的 - 意味着它正在尝试匹配从 } 的序数到 @987654329 的任何字符@'s 和介于两者之间。由于字符范围必须从低序数到高序数,125->61 是无意义的,因此错误。

在某种程度上你很幸运;如果 - 周围的字符被颠倒了,例如=-},您已经默默地删除了从序数 61 到 125(含)的所有字符,这将包括所有标准 ASCII 字母(包括小写和大写)以及一堆标点符号。

您可以通过删除角色类中的第二个- 来解决此问题(您已经将它包含在不需要转义的类的开头),从

text = re.sub(r"[-()\"#/@;:<>{}-=~|.?,]", "", text)

text = re.sub(r"[-()\"#/@;:<>{}=~|.?,]", "", text)

但我建议在这里删除正则表达式;大量文字标点符号出错的风险很高,还有其他方法根本不涉及正则表达式,它们应该可以正常工作,并且如果你逃脱了所有重要的东西也不会让你担心(替代方法是过度转义,这使得正则表达式不可读,并且仍然容易出错)。

改为将该行替换为a simple str.translate call。首先,在函数之外,make a translation table of the things to remove

# The redundant - is harmless here since the result is a dict which dedupes anyway
killpunctuation = str.maketrans('', '', r"-()\"#/@;:<>{}-=~|.?,")

然后换行:

text = re.sub(r"[-()\"#/@;:<>{}-=~|.?,]","",text)

与:

text = text.translate(killpunctuation)

它的运行速度至少应该与正则表达式一样快(可能更快),而且它更不容易出错,因为没有字符具有特殊含义(翻译表只是从 Unicode 序数到 None 的映射,意味着删除,另一个ordinal,表示单个字符替换,或字符串,表示 char -> multichar 替换;它们没有特殊转义的概念)。如果目标是消除所有 ASCII 标点符号,您可能最好使用 string 模块常量来定义翻译表(这也使代码更具自我记录性,因此人们不会怀疑您是否要删除所有或只是一些标点符号,以及是否是故意的):

import string
killpunctuation = str.maketrans('', '', string.punctuation)

碰巧的是,您现有的字符串并没有删除所有标点符号(它遗漏了^!$ 等),因此此更改可能不正确,但如果它是对的,一定能做到。如果它应该是标点符号的子集,您肯定要添加关于如何选择标点符号的注释,这样维护人员就不会怀疑您是否犯了错误。

【讨论】:

  • 谢谢,错误消失了,但标点符号没有
  • @olfamasmoudi:应该。我无法说出您的代码可能包含的其他错误。
【解决方案2】:

像我一样使用它

def clean_text(text):
    text = text.lower()
    text = re.sub('\[.*?\]', '', text)
    text = re.sub('https?://\S+|www\.\S+', '', text)
    text = re.sub('<.*?>+', '', text)
    text = re.sub('[%s]' % re.escape(string.punctuation), '', text)
    text = re.sub('\n', '', text)
    text = re.sub('\w*\d\w*', '', text)
    return text

【讨论】:

    【解决方案3】:

    您需要正确转义特殊字符并用方括号括起来

    re.sub(r'[-\(\)\"#\/@;:<>\{\}\-=~|\.\?]', '', some_text)
    

    一个更通用的正则表达式用于特殊字符(即不是字母或数字)是

    [^a-zA-Z0-9]
    

    【讨论】:

    • 注意:虽然没有害处,但大多数特殊字符在字符集中失去了它们的特殊含义,因此您不需要尽可能多的转义符(您还莫名其妙地删除了一些字符,例如 , ,从集合)。我相信r"[-()\"#/@;:&lt;&gt;{}=~|.?,]" 应该可以正常工作(仅删除第二个-,因为它已经包含在课程开头的位置,不需要转义)。
    • 支持引用from docs:“特殊字符在集合内失去其特殊含义。例如,[(+*)] 将匹配任何文字字符'(''+''*'')'。”因此,转义括号、大括号、句号、正斜杠和问号都是不必要的;仅副手 \ (任何地方)、-(在课程中间)、^(在课程开头)、]不是在开头类),并且链接中与未来嵌套集支持相关的一些随机内容([--&amp;&amp;~~||)需要转义。
    猜你喜欢
    • 1970-01-01
    • 2017-09-20
    • 1970-01-01
    • 1970-01-01
    • 2022-06-17
    • 1970-01-01
    • 2018-07-29
    • 2016-09-22
    • 1970-01-01
    相关资源
    最近更新 更多