正则表达式re.sub替换不完整的问题现象及其根本原因
2018-08-28 07:42
681 查看
title: 正则表达式re.sub替换不完整的问题现象及其根本原因
toc: true
comment: true
date: 2018-08-27 21:48:22
tags: ["Python", "正则表达式"]
category: ["Python"]
---
这段代码的使用了正则表达式的替换功能
第二个参数表示被匹配到的内容将要被替换成什么内容。由于我需要提取正文,那么只要把所有HTML标签都替换为空字符串即可。第三个参数就是需要被替换的文本,在这个例子中是HTML源代码段。
至于
现在使用一段HTML代码来测试一下:
运行效果如下图所示,功能完全符合预期
![](https://oscdn.geek-share.com/Uploads/Images/Content/201808/dcd33b624883333aa5efb2998458dc8f.png)
再来测试一下代码中有换行符的情况:
运行效果如下图所示,完全符合预期。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201808/a63cb6e10bafa8991da18d650199450c.png)
经过测试,在绝大多数情况下,能够从的HTML代码段中提取出正文。但也有例外。
运行效果如下图所示,最后两个HTML标签替换失败。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201808/162fd0fe0077f175a5f1b56a96de3ed4.png)
一开始我以为是HTML里面的空格或者引号引起的问题,于是我把HTML代码进行简化:
问题依然存在,如下图所示。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201808/dea89f06fd8916cf53ec7e8a6478dfae.png)
而且更令人惊讶的是,如果把第一个标签
![](https://oscdn.geek-share.com/Uploads/Images/Content/201808/f71295195cd01691f58176b2d60e0139.png)
实际上,不仅仅是删除第一个标签,前面任意一个标签删了都可以减少结果里面的一个标签。如果删除前面两个或以上标签,那么结果就正常了。
第四个参数是count表示替换个数,re.S如果要用,应该作为第五个参数。所以如果把
那么问题来了,把re.S放在count的位置,为什么代码没有报错?难道
现在回头数一数出问题的HTML代码,发现最后多出来的两个
至此问题的原因搞清楚了。
这个问题没有被及早发现,有以下几个原因:
被替换的HTML代码是代码段,大多数情况下HTML标签不足16个,所以问题被隐藏。
toc: true
comment: true
date: 2018-08-27 21:48:22
tags: ["Python", "正则表达式"]
category: ["Python"]
---
问题描述
问题的起因来自于一段正则替换。为了从一段HTML代码里面提取出正文,去掉所有的HTML标签和属性,可以写一个Python函数:import re def remove_tag(html): text = re.sub('<.*?>', '', html, re.S) return text
这段代码的使用了正则表达式的替换功能
re.sub。这个函数的第一个参数表示需要被替换的内容的正则表达式,由于HTML标签都是使用尖括号包起来的,因此使用
<.*?>就可以匹配所有
<xxx yyy="zzz">和
</xxx>。
第二个参数表示被匹配到的内容将要被替换成什么内容。由于我需要提取正文,那么只要把所有HTML标签都替换为空字符串即可。第三个参数就是需要被替换的文本,在这个例子中是HTML源代码段。
至于
re.S,在4年前的一篇文章中我讲到了它的用法:Python正则表达式中的re.S。
现在使用一段HTML代码来测试一下:
import re def remove_tag(html): text = re.sub('<.*?>', '', html, re.S) return text
source_1 = '''
<div class="content">今天的主角是<a href="xxx">kingname</a>,我们掌声欢迎!</div>
'''
text = remove_tag(source_1)
print(text)
运行效果如下图所示,功能完全符合预期
![](https://oscdn.geek-share.com/Uploads/Images/Content/201808/dcd33b624883333aa5efb2998458dc8f.png)
再来测试一下代码中有换行符的情况:
import re def remove_tag(html): text = re.sub('<.*?>', '', html, re.S) return text
source_2 = '''
<div class="content">
今天的主角是
<a href="xxx">kingname</a>
,我们掌声欢迎!
</div>
'''
text = remove_tag(source_2)
print(text)
运行效果如下图所示,完全符合预期。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201808/a63cb6e10bafa8991da18d650199450c.png)
经过测试,在绝大多数情况下,能够从的HTML代码段中提取出正文。但也有例外。
例外情况
有一段HTML代码段比较长,内容如下:<img></span><span>遇见kingname</span></a ><a ><span class='url-icon'>< img '></span><span >温柔</span></a ><a ><span >#青南#</span></a > <br />就在这里…<br />我的小侯爷呢???
运行效果如下图所示,最后两个HTML标签替换失败。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201808/162fd0fe0077f175a5f1b56a96de3ed4.png)
一开始我以为是HTML里面的空格或者引号引起的问题,于是我把HTML代码进行简化:
<img></span><span>遇见kingname</span></a><a><span><img></span><span>温柔</span></a><a><span>#青南#</span></a><br/>就在这里…<br/>我的小侯爷呢
问题依然存在,如下图所示。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201808/dea89f06fd8916cf53ec7e8a6478dfae.png)
而且更令人惊讶的是,如果把第一个标签
<img>删了,那么替换结果里面就少了一个标签,如下图所示。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201808/f71295195cd01691f58176b2d60e0139.png)
实际上,不仅仅是删除第一个标签,前面任意一个标签删了都可以减少结果里面的一个标签。如果删除前面两个或以上标签,那么结果就正常了。
答疑解惑
这个看起来很奇怪的问题,根本原因在re.sub的第4个参数。从函数原型可以看到:def sub(pattern, repl, string, count=0, flags=0)
第四个参数是count表示替换个数,re.S如果要用,应该作为第五个参数。所以如果把
remove_tag函数做一些修改,那么结果就正确了:
def remove_tag(html): text = re.sub('<.*?>', '', html, flags=re.S) return text
那么问题来了,把re.S放在count的位置,为什么代码没有报错?难道
re.S是数字?实际上,如果打印一下就会发现,
re.S确实可以作为数字:
>>> import re >>> print(int(re.S)) 16
现在回头数一数出问题的HTML代码,发现最后多出来的两个
<br>标签,刚刚好是第17和18个标签,而由于
count填写的
re.S可以当做16来处理,那么Python就会把前16个标签替换为空字符串,从而留下最后两个。
至此问题的原因搞清楚了。
这个问题没有被及早发现,有以下几个原因:
被替换的HTML代码是代码段,大多数情况下HTML标签不足16个,所以问题被隐藏。
re.S是一个对象,但也是数字,count接收的参数刚好也是数字。在很多编程语言里面,常量都会使用数字,然后用一个有意义的大写字母来表示。
re.S处理的情况是
<div class="123" \n>而不是
<div class="123">\n</div>但测试的代码段标签都是第二种情况,所以在代码段里面实际上加不加
re.S效果是一样的。
相关文章推荐
- 正则表达式re.sub替换不完整的问题及完整解决方案
- 软件开发问题的症状及其根本原因
- 软件开发问题的症状及其根本原因
- vue热替换失效根本原因
- IE内存泄漏的恶心问题及其原因
- 一个.NET工程在调用Java方法的时候不能创建JVM的问题及其原因
- 解决vue热替换失效的根本原因
- 举例说明Android开发中遇到的 java.lang.ClassCastException: java.lang.String这个问题的原因及其解决办法
- 解决使用base64解码太慢的问题,原因是根本就不应该使用此方法解决。
- 研发人员为什么留不住:问题与现象、原因的解析
- warning C4305: “初始化”: 从“double”到“const float”截断的问题原因及其处理
- cmos sensor camera banding 现象发生原因及相关问题
- 乱码的根本原因是字节和字符的问题(转)
- 编码问题以及其根本原因
- 编码问题以及其根本原因
- W3C不兼容问题(最根本的原因,及解决方案)
- Windows系统kernel32.dll文件出问题的原因及其解决方案
- marvell r8782 固件加载不了及其问题原因
- win7下IE8打开网页显示不完整,需要手动刷新问题的原因及解决办法
- LabVIEW编译时出现文件找不到的问题原因及其解决办法