Python中replace替换富文本编辑器中的url却匹配不到的问题如何解决

因为微信的图片有防盗链机制,复制粘贴文章每次图片都要重新传,感觉很麻烦,就想覆写下 django admin 的 save_model 方法,打算把复制来的文章的图片存到本地,如下

    def save_model(self, request, obj, form, change):
    b = etree.HTML(obj.content)
    pics = b.xpath("//*/@src")
    for pic in pics:
        c = pic.split("&")[0].split("=")
        if c[1] == "jpeg" or c[1] == "png" or c[1] == "jpg":
            img_url = pic.split("&")[0]
            image_name = img_url.replace("https://","").split("/")[2]

            new_name = settings.MEDIA_ROOT+"/"+image_name+"."+c[1]
            file_name = settings.MEDIA_URL+image_name+"."+c[1]
            response = requests.get(img_url)
            image = Image.open(BytesIO(response.content))
            image.save(new_name)

            obj.content = obj.content.replace(str(pic),str(file_name))

            print(pic)

    super(NewsAdmin,self).save_model(request, obj, form, change)

问题就出现在这句

             obj.content = obj.content.replace(str(pic),str(file_name))

想要把 富文本编辑内的原图片 url 替换成 新生成的 url 原地址也是通过 xpath 取出来的 所以应该是没有问题的 但是 replace 就是一直匹配不到原 url 即使加了去掉换行符,依旧匹配不到

                  obj.content = obj.content.replace('\r','').replace('\n','').replace('\t','')

有点懵了,还请各位指点一下


Python中replace替换富文本编辑器中的url却匹配不到的问题如何解决

2 回复

我遇到过这个问题,富文本编辑器生成的HTML里URL经常被各种属性包裹,直接匹配纯文本URL确实会失败。

核心问题是富文本中的URL通常被包装在HTML标签里,比如:

text = '<a href="https://example.com/page?id=123">点击这里</a>'
# 直接replace("https://example.com/page?id=123", "new_url") 是匹配不到的

你需要用正则表达式处理HTML内容:

import re

def replace_url_in_html(html_content, old_url, new_url):
    """
    在HTML内容中安全替换URL
    
    参数:
        html_content: 包含HTML的字符串
        old_url: 要替换的原始URL
        new_url: 替换后的新URL
    """
    # 转义特殊字符,确保正则匹配安全
    escaped_old_url = re.escape(old_url)
    
    # 匹配各种可能包含URL的HTML属性
    patterns = [
        rf'href=["\']{escaped_old_url}["\']',  # href属性
        rf'src=["\']{escaped_old_url}["\']',   # src属性
        rf'url\({escaped_old_url}\)',          # CSS url()中的URL
    ]
    
    for pattern in patterns:
        html_content = re.sub(
            pattern, 
            lambda m: m.group(0).replace(old_url, new_url), 
            html_content, 
            flags=re.IGNORECASE
        )
    
    return html_content

# 使用示例
html = '<a href="https://old.com/page">链接</a><img src="https://old.com/image.jpg">'
new_html = replace_url_in_html(html, "https://old.com/", "https://new.com/")
print(new_html)

如果富文本内容特别复杂,建议用专门的HTML解析库:

from bs4 import BeautifulSoup

def replace_url_with_bs4(html_content, old_url, new_url):
    soup = BeautifulSoup(html_content, 'html.parser')
    
    # 替换所有标签的href属性
    for tag in soup.find_all(href=re.compile(re.escape(old_url))):
        tag['href'] = tag['href'].replace(old_url, new_url)
    
    # 替换所有标签的src属性  
    for tag in soup.find_all(src=re.compile(re.escape(old_url))):
        tag['src'] = tag['src'].replace(old_url, new_url)
    
    return str(soup)

关键是要理解富文本是HTML,不是纯文本。用字符串的replace()方法处理HTML就像用剪刀修电路板——工具用错了。

总结:用正则或HTML解析器处理富文本中的URL替换。


找到问题了…原 url 中有很多&amp;…

回到顶部