LinuxEye - Linux系统教程

LinuxEye - Linux系统教程

当前位置: 主页 > 脚本编程 >

如何精确替换第n个匹配到的文本?

时间:2014-09-05 18:25来源:未知 编辑:linuxeye 点击:
无论搜索引擎公司还是数据分析公司,都需要构建爬虫来定制抓取工作,如何处理抓回来的文本奠定了存储和分析的基础。文章类页面(如新闻,博客等)的抓取和解析已经比较成熟了
无论搜索引擎公司还是数据分析公司,都需要构建爬虫来定制抓取工作,如何处理抓回来的文本奠定了存储和分析的基础。文章类页面(如新闻,博客等)的抓取和解析已经比较成熟了,标题和正文的抽取准确性已经很高,也是 Pocket,Evernote Clearly,Readability 等服务的基础。BBS 页面的解析则是一个比较麻烦的问题,如果将主贴和评论拆成不同的「文章」进行抓取,就需要对二者进行关联,所以在解析后续页面时如何确定首页链接就成了一个必须解决的问题。考虑到通用性,最终我决定使用当前页的 URL 和翻页操作区域出现的各页面 URL 确定首页链接,基本思想就是找出这些 URL 中唯一不同的数字并替换为首页的页号。那么,在 Python 中如何精确替换一段文本中出现的第 N 个数字呢?

最初想确定页号的起始位置之后用字符串切片和拼接完成替换,但是有些不太优雅。stackoverflow 上有一些解决方案都没有结合正则,思想上都是维护一个变量,然后匹配到第 N 次的时候才执行替换。那么对于这种很常见的需求,re 模块中难道就没有内建的支持吗?仔细阅读了一下 re 模块文档中的 sub 函数说明,发现了一个原来没有注意到的特性:

    If repl is a function, it is called for every non-overlapping occurrence of pattern. The function takes a single match object argument, and returns the replacement string. For example:
 

大意是如果 sub 函数的第二个参数是个函数,则每次匹配到的时候都会执行这个函数。函数接受匹配到的那个 match object 作为参数,返回用来替换的字符串。利用这个特性就可以只在第 N 次匹配的时候返回要替换成的字符串,其他时候原样返回不做替换即可。

现在就只需要考虑如何维护一个在多次调用时不被重置的变量,最终在 Python 邮件列表中找到一个帖子使用类变量而非全局变量优雅地解决了这个问题。根据我的需要修改后的代码如下:
class Nth(object):
    def __init__(self, nth, replacement):
        self.nth = nth
        self.replacement = replacement
        self.calls = 0
 
    def __call__(self, matchobj):
        self.calls += 1
        if self.calls == self.nth:
            return self.replacement
        return matchobj.group(0)
最后调用的时候如下执行即可获得首页链接:
re.sub('\d+', Nth(i, '1'), url)

转载请保留固定链接: https://linuxeye.com/program/2017.html

------分隔线----------------------------
标签:Python
栏目列表
推荐内容