推荐学习书目
› Learn Python the Hard Way
Python Sites
› PyPI - Python Package Index
› http://diveintopython.org/toc/index.html
› Pocoo
值得关注的项目
› PyPy
› Celery
› Jinja2
› Read the Docs
› gevent
› pyenv
› virtualenv
› Stackless Python
› Beautiful Soup
› 结巴中文分词
› Green Unicorn
› Sentry
› Shovel
› Pyflakes
› pytest
Python 编程
› pep8 Checker
Styles
› PEP 8
› Google Python Style Guide
› Code Style from The Hitchhiker's Guide
xixitalk
V2EX  ›  Python

[请教]文本里多个 URL 处理

  •  
  •   xixitalk · Oct 1, 2016 · 4330 views
    This topic created in 3695 days ago, the information mentioned may be changed or developed.
    文本要在浏览器显示,把 URL 都转换成了 HTML 超级链接。文本里可能出现多个 URL 网址。

    目前流程处理流程是:
    1 、正则表达式提取 URl 的 list
    2 、遍历 list 进行 replace 替换。比如: g.cn 替换成<a href="g.cn">g.cn</a>

    现在遇到这样的问题:
    如果一个 URL 包含另一个 URL ,替换就出现错乱。 replace 短 URL 会把长的 URL 替换搞乱。

    这个应该用什么流程来处理比较合适。
    22 replies  •  2016-10-01 16:51:19 +08:00
    msg7086
    msg7086
    Oct 1, 2016
    1
    举个栗子?
    imn1
    imn1
    Oct 1, 2016
    2
    先把文本格式写出来才能讨论
    lxy42
    lxy42
    Oct 1, 2016 via Android
    3
    正则表达式兼容 URL 中包含参数的情况
    xiaojj
    xiaojj
    Oct 1, 2016
    4
    按你匹配的结果按顺序一个一个替换,不要一次性把文本里面的 g.cn 都替换成链接的 html
    xixitalk
    xixitalk
    OP
    Oct 1, 2016 via Android
    6
    文本例子
    文本:第一个地址: http://g.cn 第二个地址: http://g.cn/1234

    替换后:第一个地址:<a href="http://g.cn">http://g.cn</a> 第二个地址:<a href="http://g.cn/1234">http://g.cn/1234</a>
    xixitalk
    xixitalk
    OP
    Oct 1, 2016 via Android
    7
    正则表达式提取了整个 URL ,包括参数的
    xixitalk
    xixitalk
    OP
    Oct 1, 2016 via Android
    8
    @ebony0319 不是,这是一个 URL,不是多个
    zjuhwc
    zjuhwc
    Oct 1, 2016 via iPhone
    9
    你提取 URL 用的正则都可以提取出出 g.cn 和 g.cn/1234 两种情况,那替换的时候就用一样的规则替换啊
    xixitalk
    xixitalk
    OP
    Oct 1, 2016 via Android
    10
    @xiaojj 正则替换吗?直接 replace 不好写吧
    xixitalk
    xixitalk
    OP
    Oct 1, 2016 via Android
    11
    @zjuhwc 替换 g.cn 的时候会把 g.cn/1234 里前半部分替换掉,后者会变成<a href="http://g.cn">http://g.cn</a>/1234 这样的。
    zjuhwc
    zjuhwc
    Oct 1, 2016 via iPhone
    12
    @xixitalk 你提取的时候是怎么做到提取的是 g.cn/1234 而不是 g.cn 的?
    zjuhwc
    zjuhwc
    Oct 1, 2016
    13
    哦,看明白了,你想用 replace 。问题是你都用正则提取了,为啥不直接用正则替换。比如你提取用的是 re.match(pattern, string) ,你可以直接用 re.sub(pattern, repl, string, max=0) 做正则替换,复用之前的 pattern 啊
    buir
    buir
    Oct 1, 2016
    14
    很简单 写个软件就可以了~
    aploium
    aploium
    Oct 1, 2016
    15
    这是因为你正则写得不好啊
    自行 google 一下 "regex url"
    aploium
    aploium
    Oct 1, 2016
    16
    还有正则引擎一般都带有 sub 功能的, 就是直接把匹配到的东西原地替换
    比如(Python)

    >>>re.sub(r"( http://go\.cn)",r"""<a href="\1">\1</a>""", "http://go.cn")
    <a href="http://go.cn">http://go.cn</a>
    moxiaonai
    moxiaonai
    Oct 1, 2016 via iPhone
    17
    正则写的更准确一点应该能解决
    Shazoo
    Shazoo
    Oct 1, 2016
    18
    1. 正则原地替换
    2. 如果觉得正则替换代码可读性低了点,不好维护,就在创建 list 的时候,保留这个 sub 字串的 pos ,后续在利用 pos 进行替换。

    粗略一想,没试验,用哪种,还是自己评估。


    不过我个人建议方案 1 。正则这东西,就是个坎,肯定得学习到一定程度的。长痛不如短痛,好好记忆吧。
    arnofeng
    arnofeng
    Oct 1, 2016 via iPhone
    19
    正则没写好 你要匹配到斜杠的
    imn1
    imn1
    Oct 1, 2016
    20
    还是没有说清楚格式
    如果每行一个 url
    ^(.+)$ -> <a href="$1">$1</a><br>
    就够了
    如果是没有分行,就要说清楚 url 之间是怎么分隔的
    xixitalk
    xixitalk
    OP
    Oct 1, 2016
    21
    感谢,写了一个能用的

    def convertMsgToHTML(msg):
    #urls = re.findall('http[s]?://(?:#|[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', msg)
    msg = re.sub(r'( http[s]?://(?:#|[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)', r'<a href="\g<1>" target="_blank">\g<1></a>',msg,count=0,flags=re.UNICODE|re.MULTILINE)
    return msg

    测试:
    msg = u'''特殊 123 http://g.cn 456 http://g.cn/1234 78910 汉字
    '''
    text = convertMsgToHTML(msg)

    print text.encode('utf-8')


    输出结果:
    特殊 123 <a href="http://g.cn" target="_blank">http://g.cn</a> 456 <a href="http://g.cn/1234" target="_blank">http://g.cn/1234</a> 78910 汉字
    xixitalk
    xixitalk
    OP
    Oct 1, 2016
    22
    我现在明白推特的 tweet 结构里不仅保存了缩短的地址 url ,还有展开地址 expand_url ,还有一个显示地址 disp_url 。不然推文转换成 html 太低效率了。

    缩短的地址保证了地址唯一性(当然还有数据统计方面的作用)
    展开地址是用户原始输入的地址
    显示地址保证了原始地址过长只显示前面 30 字节左右,排版美观。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   2389 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 41ms · UTC 04:51 · PVG 12:51 · LAX 20:51 · JFK 23:51
    ♥ Do have faith in what you're doing.