Python正则表达式将YouTube网址转换为视频链接

6 投票
4 回答
9309 浏览
提问于 2025-04-16 10:03

我正在写一个正则表达式,用来在用户发布的HTML文本中找到YouTube链接(可能有多个)。

现在我使用的正则表达式可以把这样的链接 'http://www.youtube.com/watch?v=-JyZLS2IhkQ' 转换成可以显示相应YouTube视频的格式:

return re.compile('(http(s|):\/\/|)(www.|)youtube.(com|nl)\/watch\?v\=([a-zA-Z0-9-_=]+)').sub(tag, value)

(这里的'变量tag'是一些HTML代码,让视频可以正常工作,而'value'是用户的帖子内容)

目前这个方法有效……直到链接变成这样:

'http://www.youtube.com/watch?v=-JyZLS2IhkQ&feature...'

现在我希望你们能帮我想办法,让'&feature...'这一部分也能被匹配到,这样它就会消失。

示例HTML:

No replies to this post..

Youtube vid:

http://www.youtube.com/watch?v=-JyZLS2IhkQ

More blabla

谢谢你们的建议,非常感谢

斯特凡

4 个回答

3

如果你使用urlparse模块来解析你找到的YouTube地址,然后把它重新整理成你想要的格式,这样就可以简化你的正则表达式,让它只找到完整的URL,然后用urlparse来帮你处理复杂的解析工作。

from urlparse import urlparse,parse_qs,urlunparse
from urllib import urlencode
youtube_url = urlparse('http://www.youtube.com/watch?v=aFNzk7TVUeY&feature=grec_index')
params = parse_qs(youtube_url.query)
new_params = {'v': params['v'][0]}

cleaned_youtube_url = urlunparse((youtube_url.scheme, \
                                  youtube_url.netloc, \
                                  youtube_url.path,
                                  None, \
                                  urlencode(new_params), \
                                  youtube_url.fragment))

虽然这样需要写更多的代码,但可以避免正则表达式的复杂性。

而且正如hop所说,使用原始字符串来写正则表达式会更好。

5

你应该把正则表达式写成原始字符串。

你不需要对每个看起来特别的字符都加上转义,只需要对那些真的特殊的字符进行转义。

如果你想让某个部分变成可选的,不需要写一个空的分支((foo|)),可以直接用 ?

如果你想在字符集中包含 -,你需要对它进行转义,或者把它放在开括号后面紧接着的位置。

你可以使用像 \w 这样的特殊字符集(它等于 [a-zA-Z0-9_])来简化你的正则表达式。

r'(https?://)?(www\.)?youtube\.(com|nl)/watch\?v=([-\w]+)'

现在,为了匹配整个网址,你需要考虑在输入中什么可以跟在网址后面,什么不可以。然后把这些放进一个前瞻组里(你不想消耗掉它)。

在这个例子中,我选择了除了 -=%& 和字母数字字符以外的所有东西来结束网址(懒得再想得更复杂了)。

在 v-参数和网址结束之间的所有内容都被 .*? 非贪婪地消耗掉了。

r'(https?://)?(www\.)?youtube\.(com|nl)/watch\?v=([\w-]+)(&.*?)?(?=[^-\w&=%])'

不过,我还是不太相信这个通用的解决方案。用户输入通常很难稳健地解析。

7

这是我解决这个问题的方法:

import re

def youtube_url_validation(url):
    youtube_regex = (
        r'(https?://)?(www\.)?'
        '(youtube|youtu|youtube-nocookie)\.(com|be)/'
        '(watch\?v=|embed/|v/|.+\?v=)?([^&=%\?]{11})')

    youtube_regex_match = re.match(youtube_regex, url)
    if youtube_regex_match:
        return youtube_regex_match

    return youtube_regex_match

测试:

youtube_urls_test = [
    'http://www.youtube.com/watch?v=5Y6HSHwhVlY',
    'http://youtu.be/5Y6HSHwhVlY', 
    'http://www.youtube.com/embed/5Y6HSHwhVlY?rel=0" frameborder="0"',
    'https://www.youtube-nocookie.com/v/5Y6HSHwhVlY?version=3&hl=en_US',
    'http://www.youtube.com/',
    'http://www.youtube.com/?feature=ytca']


for url in youtube_urls_test:
    m = youtube_url_validation(url)
    if m:
        print('OK {}'.format(url))
        print(m.groups())
        print(m.group(6))
    else:
        print('FAIL {}'.format(url))

撰写回答