2011-01-16 33 views
5

estoy haciendo una expresión regular para que pueda encontrar enlaces de youtube (puede ser múltiple) en un trozo de texto HTML Publicado por un usuario.Python expresiones regulares convertir youtube url para youtube video

Actualmente estoy usando la siguiente expresión regular para cambiar 'http://www.youtube.com/watch?v=-JyZLS2IhkQ' en mostrar la correspondiente video de youtube:

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

(donde la variable 'etiqueta' es un poco de html por lo que las obras de vídeo y una entrada de usuario 'valor')

Ahora esto funciona .. hasta que la URL es la siguiente:

'http://www.youtube.com/watch? v = -JyZLS2IhkQ función & ...'

Ahora estoy esperando ustedes podrían ayudarme a descubrir cómo hacer coincidir también la 'característica & ...' parte por lo que desaparece.

Ejemplo HTML:

No replies to this post.. 

Youtube vid: 

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

More blabla 

Gracias por sus pensamientos, muy apreciada

Stefan

+3

su expresión regular es bastante atroz :) – hop

+0

esperar qué? ¿Estás tratando de encontrar un enlace de youtube enterrado en algún código html? ¡Me costó analizar eso de tu pregunta! – hop

+0

Lamento la mala pregunta, cambié la publicación, espero que ahora esté más claro. – Frits

Respuesta

4

Debe especificar sus expresiones regulares como cadenas primas.

Usted no tiene que escapar a todos los personajes que se ve especiales, sólo los que son .

En lugar de especificar una rama vacía ((foo|)) para hacer algo opcional, puede usar ?.

Si desea incluir - en un juego de caracteres, tiene que escapar o ponerlo justo después del corchete de apertura.

Puede usar juegos de caracteres especiales como \w (es igual a [a-zA-Z0-9_]) para acortar su expresión regular.

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

Ahora, con el fin de que coincida con la URL completa, usted tiene que pensar en lo que puede o no puede seguirla en la entrada. Luego pones eso en un grupo de anticipación (no quieres consumirlo).

En este ejemplo Tomé todo excepto -, =, %, & y caracteres alfanuméricos para poner fin a la URL (demasiado perezosos para pensar en ello con más fuerza).

Todo lo que se encuentra entre el argumento v y el final de la URL no es codiciosamente consumido por .*?.

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

Aún así, no le daría mucha fe a esta solución general. La entrada del usuario es notoriamente difícil de analizar robustamente.

3

¿Qué pasa si usó el urlparse module para separar la dirección de youtube que encuentra y ponerla nuevamente en el formato que desea? Luego puede simplificar su expresión regular para que solo encuentre la url completa y luego use urlparse para hacer el trabajo pesado de separarla por usted.

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)) 

Es un poco más código, pero te permite evitar la locura regex.

Y como dijo hop, deberías usar cadenas sin formato para la expresión regular.

+0

Di (y eliminé) la misma respuesta, pero el problema es "encontrar" la URL, no analizarla. – hop

+0

Bueno, él quiere hacer las dos cosas. Quiere encontrar la url y analizarla (porque necesita deshacerse de una parte de la cadena de consulta). Mi sugerencia fue encontrar la url primero, que su expresión regular ya hace según la pregunta. Y luego use un código ya existente para separarlo y quitarle lo que no quiere o no necesita. – seggy

5

Aquí cómo estoy resolverlo:

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.group(6) 

    return youtube_regex_match 

pruebas:

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) 
+2

Para hacer coincidir las URL como 'http://www.youtube.com/watch?feature=player_detailpage & v = QemTZn8YfJ0 # t = 46s' He editado tu expresión regular en' youtube_regex = ( r '(https?: //)? (www \.)? ' ' (youtube | youtu | youtube-nocookie) \. (com | be)/' ' (reloj \?. *? (? = v =) v = | embed/| v/|. + \? v =)? ([^ & =% \?] {11}) ') ' –

0

Así es como he implementado en mi guión:

string = "Hey, check out this video: https://www.youtube.com/watch?v=bS5P_LAqiVg" 

youtube = re.findall(r'(https?://)?(www\.)?((youtube\.(com))/watch\?v=([-\w]+)|youtu\.be/([-\w]+))', string) 

if youtube: 
    print youtube 

que da salida:

["", "youtube.com/watch?v=BS5P_LAqiVg", ".com", "watch", "com", "bS5P_LAqiVg", ""] 

Si sólo quería agarrar el ID de vídeo, por ejemplo, puede hacer:

video_id = [c for c in youtube[0] if c] # Get rid of empty list objects 
video_id = video_id[len(video_id)-1] # Return the last item in the list 
Cuestiones relacionadas