0

URLを作業リンクに変換する関数を書いています。これはすべての形式を変換する必要があります: のような完全な url http://link.com、プロトコルのようなものなし、www.link.com拡張子のようなものだけでもlink.com

これまでのところ、私の関数は機能していますが、文字列に同じリンクが複数回あると奇妙なバグがあります。

import re
import cgi

def process_links(string):
    """Convert urls to links in a string"""
    # http + https
    links = re.findall("(https?://[^\s]+)", string)
    # www
    links2 = re.findall("(w{3}\.[^\s]+)", string)
    # only extension
    links3 = re.findall("([^\s]+\.[^\s]{2,})", string)
    links = links + links2 + links3
    # remove duplicates
    links = list(set(links))
    string = cgi.escape(string)
    for link in links:
        # make sure the href attr starts with http|https
        if re.match('https?://', link) is None:
            http_link = 'http://'+link
        else:
            http_link = link
        htmlLink = '<a href="'+http_link+'">'+link+'</a>'
        string = re.sub(link, htmlLink, string)
    return string

動作例と失敗例:

# working
string = 'firstlink.com and www.secondlink.com'
# output:
# '<a href="http://firstlink.com">firstlink.com</a> and <a href="http://www.secondlink.com">www.secondlink.com</a>    

# failing: when there are several times the same link
string = 'firstlink.com and http://firstlink.com
# output:
# <a href="<a href="http://firstlink.com">http://firstlink.com</a>">firstlink.com</a> and http://<a href="<a href="http://firstlink.com">http://firstlink.com</a>">firstlink.com</a>

Pythonでこの「複雑な」正規表現を使用しようとしたことはなく、なぜこの奇妙な動作があるのか​​ わかりません。re.sub()これは、すでに置き換えられているものを置き換える可能性がある部分から来ていると思いますか?

PS: 私の機能はおそらく最高ではなく、確実に改善される可能性があります。何か提案があれば聞いています。

4

1 に答える 1

0

リンクを見つけ次第処理し、すべてのフォームを1 つの正規表現で検索します。re.sub()と置換関数を使用するのが最も簡単です。

def linkify(match):
    link = match.group(1)
    http_link = link if re.match('https?://', link) else 'http://' + link
    return '<a href="{}">{}</a>'.format(http_link, link)

links = re.compile(r'(https?://[^\s]+|w{3}\.[^\s]+|[^\s]+\.[^\s]{2,})')
string = links.sub(linkify, string)

3 つの形式を 1 つのパターンに結合することで、同じリンクが複数回一致することを防ぎます。また、置換機能を使用することで、同じリンクの短い形式が使用されている複数の出現を置換することも回避できます (リンクには、将来の置換呼び出しのためhttp://firstlink.comの部分が含まれています)。 firstlink.com)。

デモ:

>>> string = 'firstlink.com and www.secondlink.com'
>>> links.sub(linkify, string)
'<a href="http://firstlink.com">firstlink.com</a> and <a href="http://www.secondlink.com">www.secondlink.com</a>'
>>> string = 'firstlink.com and http://firstlink.com'
>>> links.sub(linkify, string)
'<a href="http://firstlink.com">firstlink.com</a> and <a href="http://firstlink.com">http://firstlink.com</a>'
于 2013-06-04T23:05:10.437 に答える