正则表达式匹配失效及SEC文件文本清理异常问题排查
SEC文件文本清理问题排查与解决
问题描述
我正尝试从SEC文件中解析特定数据,目前在清理该类表单的.txt版本中的冗余信息。我使用re.compile创建正则对象,再通过re.sub将匹配到的字符串替换为单个空格,代码如下:
url = 'https://www.sec.gov/Archives/edgar/data/1848898/000119312521068620/0001193125-21-068620.txt' response = requests.get(url, headers = {'User-Agent':'placeholder@emailaddress.com'}).text formatted_response = response.replace('\n',' ').replace('\t',' ') underwriters_begin = formatted_response[re.search(r'<B>Underwriters</B>|<B>Underwriter</B>|Underwriter<\/FONT>', formatted_response).span()[0]:] underwriters_text = underwriters_begin[:re.search(r'\d+,\d+,\d+', underwriters_begin).span()[1]] cleaner = re.compile('\s{2,}|<.*?>|&\S+|Underwriter\w*|Total|Number\s*of\s*Units') clean_text = re.sub(cleaner, ' ', underwriters_text) clean_text
但输出结果仍存在大量连续空格,且“Number of Units”文本未被移除。想知道为何正则中的\s{2,}部分未替换2个及以上的空格,同时“Number of Units”未被删除,这是编码问题吗?
问题原因与解决办法
1. 连续空格未被处理的原因
你当前的正则是把所有匹配项(包括连续空格、HTML标签、关键词等)一次性替换为空格,但一次re.sub只会处理原字符串中已有的匹配项。比如,当你把HTML标签替换成空格后,原来的标签位置会变成空格,和周围的空格拼接成新的连续空格,这些新产生的连续空格不会被这次re.sub处理,因为替换是基于原字符串的匹配结果进行的。
解决办法:
分两步处理:
- 第一步:先把所有需要移除的内容(标签、关键词等)替换成空格
- 第二步:单独用正则把所有连续空格(包括替换后产生的)替换成单个空格
2. “Number of Units”未被移除的原因
不是编码问题,是正则匹配不到。SEC文件里常用HTML的 (不间断空格)来排版,转成文本后是ASCII码为160的字符(\u00A0),而Python正则里的\s默认只匹配普通空格、制表符、换行等,不包含不间断空格。你的正则Number\s*of\s*Units里的\s*匹配不到 转成的空格,所以整个短语匹配失败。
解决办法:
先把所有不间断空格替换成普通空格,再用正则匹配,这样\s*就能正常识别中间的空格了。
修正后的完整代码
import re import requests url = 'https://www.sec.gov/Archives/edgar/data/1848898/000119312521068620/0001193125-21-068620.txt' response = requests.get(url, headers={'User-Agent':'placeholder@emailaddress.com'}).text # 新增:把不间断空格(\u00A0)替换成普通空格,同时处理换行、制表符 formatted_response = response.replace('\n',' ').replace('\t',' ').replace('\u00A0', ' ') underwriters_begin = formatted_response[re.search(r'<B>Underwriters</B>|<B>Underwriter</B>|Underwriter</FONT>', formatted_response).span()[0]:] underwriters_text = underwriters_begin[:re.search(r'\d+,\d+,\d+', underwriters_begin).span()[1]] # 正则不需要修改,因为已经把不间断空格换成了普通空格 cleaner = re.compile(r'\s{2,}|<.*?>|&\S+|Underwriter\w*|Total|Number\s*of\s*Units') # 第一步:替换所有冗余内容为空格 clean_text = re.sub(cleaner, ' ', underwriters_text) # 第二步:统一处理所有连续空格,替换为单个空格,最后去掉首尾空格 clean_text = re.sub(r'\s+', ' ', clean_text).strip() print(clean_text)
内容的提问来源于stack exchange,提问作者MK009
相关产品推荐
相关产品推荐

