【问题标题】:Hyphen character '-' creating issues when using regular expressions for BeautifulSoup在为 BeautifulSoup 使用正则表达式时,连字符“-”会产生问题
【发布时间】:2019-07-19 21:38:54
【问题描述】:

我正在学习如何使用维基百科文章使用 python 进行网络爬虫。通过对表行 () 使用 .get_text() 方法,我设法获取了我需要的数据、表。

我正在清理 Pandas 中的数据,其中一个例程涉及获取书籍或电影的出版日期。由于发生这种情况的方式有很多,例如: (1986) (1986-1989) (1986 年至今)

目前,我正在使用下面的代码来处理测试句:

# get the first columns of row 19 from the table and get its text
test = data_collector[19].find_all('td')[0]
text = test.get_text()
#create and test the pattern
pattern = re.compile('\(\d\d\d\d\)|\(\d\d\d\d-\d\d\d\d\)|\(\d\d\d\d-[ Ppresent]*\)')
re.findall(pattern, 'This is Agent (1857), the years were (1987-1868), which lasted from (1678- Present)')

我得到了测试句子的预期输出。

['(1857)', '(1987-1868)', '(1678- Present)']

但是,当我在维基文章“福尔摩斯历险记 (1891–1892) (系列), (1892) (小说), Arthur Conan Doyle\n',我可以提取 (1892),但不能提取 (1891-1892)。

text = test.get_text()
re.findall(pattern, text)
o/p: ['(1892)']

即使在我输入此内容时,我也可以看到我使用的连字符与文本上的连字符不同。我确信这就是问题所在,并希望有人能告诉我这个特殊符号的名称以及我如何使用键盘实际“键入”它。

谢谢!

【问题讨论】:

  • 你确定有连字符而不是破折号吗?试试re.compile(r'\(\d{4}(?:[\s–—-]+(?:\d{4}|present))?\)', re.I)。请参阅regex demo
  • 如果你可以使用regex,你可以使用Unicode字符类别\p{Pd}来匹配所有的破折号——见stackoverflow.com/q/1832893/3001761
  • 我同意@Wiktor,这个角色可能并不完全像它看起来的那样。另一种解决方案是将“-”替换为“\S”。含义匹配任何非空白字符
  • \p{Pd} 包含很多symbols similar to hyphen。有些看起来不像连字符。然后使用\u002D\u058A\u05BE\u1400\u1806\u2010-\u2015\u2E17\u2E1A\u2E3A\u2E3B\u2E40\u301C\u3030\u30A0\uFE31\uFE32\uFE58\uFE63\uFF0D 而不是连字符/破折号。或者,匹配任何非单词字符,可能除了()[^\w()] => re.compile(r'\(\d{4}(?:[^\w()]+(?:\d{4}|present))?\)', re.I)
  • @WiktorStribiżew 谢谢!您的解决方案完美无缺。

标签: python regex beautifulsoup


【解决方案1】:

我建议增强模式以搜索最常见的连字符-,并将present 模式从字符类修复为字符序列(以免匹配@ 987654326@ 和[ Ppresent]*):

re.compile(r'\(\d{4}(?:[\s–—-]+(?:\d{4}|present))?\)', re.I)

请参阅regex demo。请注意,re.I 标志将使正则表达式以不区分大小写的方式匹配。

详情

  • \( - 一个(
  • \d{4} - 四位数字({4} 是一个限制量词,它重复它修改四次的模式)
  • (?:[\s–—-]+(?:\d{4}|present))? - 一个可选的(因为末尾有一个 ?)非捕获(由于 ?:)组匹配 1 或 0 个出现
    • [\s–—-]+ - 1 个或多个空格,-
    • (?:\d{4}|present) - 4 位数字或 present
  • \) - ) 字符。

如果您打算匹配任何连字符,请使用 [\u002D\u058A\u05BE\u1400\u1806\u2010-\u2015\u2E17\u2E1A\u2E3A\u2E3B\u2E40\u301C\u3030\u30A0\uFE31\uFE32\uFE58\uFE63\uFF0D\s]+ 而不是 [\s–—-]+

或者,要匹配该位置的任何 1+ 个非单词字符,可能,除了 (),请改用 [^\w()]+re.compile(r'\(\d{4}(?:[^\w()]+(?:\d{4}|present))?\)', re.I)

【讨论】:

    猜你喜欢
    • 2011-12-16
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多