Python re.search匹配网页爬取的西班牙法律文本始终返回None的问题排查
问题根因
你遇到的正则匹配失败完全不是正则规则、编码、系统环境的问题,本质是爬取拿到的字符串和肉眼看到的文本存在肉眼不可见的字符差异:
- 你爬取的阿根廷官方公报站点,正文里大量使用不间断空格(Unicode编码
U+00A0,Python中转义为\xa0),这种空格和我们平时输入的半角空格视觉上完全没有区别,但属于完全不同的字符。 - BeautifulSoup提取
.text属性时,会把页面里夹着的全角空格、零宽字符、标签间换行、缩进原封不动保留下来;控制台打印这些内容时,所有特殊空白字符都会被渲染成和普通空格一样的视觉效果。你把控制台打印的内容复制出来硬编码测试时,编辑器会自动把这些特殊空白转换成普通半角空格,因此才会出现“硬编码能匹配、直接用爬取返回值匹配就失败”的诡异现象。
可直接落地的解决步骤
1. 先对爬取文本做标准化清洗
拿到BeautifulSoup提取的文本后,不要直接丢给正则匹配,先统一把所有同形不同码的字符转换成标准形式:
import unicodedata # 原爬取逻辑获取文本后,追加清洗流程 b = a.find('h6').text # 先替换高频出现的特殊空格为普通半角空格 b = b.replace('\xa0', ' ').replace('\u3000', ' ') # 用Unicode NFKC规则做归一,统一所有全角/半角同形字符 b = unicodedata.normalize('NFKC', b) # 把连续多个空白压缩成单个半角空格,去掉首尾冗余空白 b = ' '.join(b.strip().split())
清洗完成后再和你硬编码的参考字符串对比,b == c就会返回完全一致的结果。
2. 优化正则的匹配容错性
你之前写的正则硬编码了一个普通半角空格作为匹配前缀,只要碰到特殊空格就会直接匹配失败。可以把固定的半角空格替换为通用空白匹配规则,自动适配不同类型的空白字符:
# 简化原有的[o]?[a]?写法为[oa]?(单位置要么是o、要么是a、要么为空) # 把固定半角空格替换为\s*,匹配任意数量的任意类型空白 if re.search(r"\s*Dase por designad[oa]?", b, re.UNICODE) is not None: return "I'm gonna read it" else: return "I'm not gonna read it"
快速排查差异的小技巧
如果清洗优化后仍匹配失败,可以逐字符输出爬取文本的编码,10秒定位差异:
# 逐位置输出字符和对应Unicode编码,直接找到和参考字符串不一样的位置 for idx, char in enumerate(b): print(f"位置{idx}: 字符'{char}', 编码{hex(ord(char))}")
跑这段代码大概率会在Dase关键词的前置位置看到编码为0xa0的不间断空格,这就是之前让正则匹配失败的核心诱因。
内容的提问来源于stack exchange,提问作者Juanse
相关产品推荐
相关产品推荐

