2011-08-22 22 views
5

he visto este hilo ya - How can I unshorten a URL?¿Cómo puedo acortar una URL usando Python?

Mi problema con la respuesta resuelto (es decir, utilizando la API unshort.me) es que me estoy centrando en unshortening enlaces de YouTube. Como unshort.me se usa fácilmente, devuelve casi el 90% de los resultados con captchas que no puedo resolver.

Hasta ahora estoy atascado con el uso de:

def unshorten_url(url): 
    resolvedURL = urllib2.urlopen(url) 
    print resolvedURL.url 

    #t = Test() 
    #c = pycurl.Curl() 
    #c.setopt(c.URL, 'http://api.unshort.me/?r=%s&t=xml' % (url)) 
    #c.setopt(c.WRITEFUNCTION, t.body_callback) 
    #c.perform() 
    #c.close() 
    #dom = xml.dom.minidom.parseString(t.contents) 
    #resolvedURL = dom.getElementsByTagName("resolvedURL")[0].firstChild.nodeValue 
    return resolvedURL.url 

Nota: todo en los comentarios es lo que he intentado hacer al utilizar el servicio unshort.me el que regresaba enlaces captcha.

¿Alguien sabe de una forma más eficiente de completar esta operación sin usar abrir (ya que es un desperdicio de ancho de banda)?

+0

Lo acortador de url estás teniendo problemas con? ¿Por qué estás usando unshort.me de todos modos? Su código ya debería funcionar, debería deshabilitar las URL siguiendo la redirección a la url real. – zeekay

+0

No entiendo lo que quiere decir con "sin usar abierto". Un enlace corto es una clave en la base de datos de otra persona; no puede expandir el enlace sin consultar la base de datos. –

+0

Cuando estaba leyendo la publicación a la que hice referencia (http://stackoverflow.com/questions/4201062/how-can-i-unshorten-a-url-using-python) se veía como ese comando urlopen GET solicita toda la página así que es un desperdicio de ancho de banda cuando todo lo que estoy buscando es el enlace. El método sugerido no funcionaba para mí (unshort.me), así que decidí ver si había otras alternativas. – brandonmat

Respuesta

14

Utilice la respuesta mejor valorados (no la respuesta aceptada) en esta pregunta:

# This is for Py2k. For Py3k, use http.client and urllib.parse instead, and 
# use // instead of/for the division 
import httplib 
import urlparse 

def unshorten_url(url): 
    parsed = urlparse.urlparse(url) 
    h = httplib.HTTPConnection(parsed.netloc) 
    resource = parsed.path 
    if parsed.query != "": 
     resource += "?" + parsed.query 
    h.request('HEAD', resource) 
    response = h.getresponse() 
    if response.status/100 == 3 and response.getheader('Location'): 
     return unshorten_url(response.getheader('Location')) # changed to process chains of short urls 
    else: 
     return url 
+0

Funcionó a las mil maravillas. Intenté esto ayer sin ningún resultado, ya que recibía errores en aproximadamente el 70% de los beneficios. Puede haber sido algo único y por eso lo descarté. Gracias por su respuesta y lo siento por mi pregunta redundante. – brandonmat

+2

Como seguimiento, solo recuerdo por qué esta manera no funcionó para mí. Estoy trabajando en una aplicación de Twitter y hay casos en que una url se acorta dos veces (lo que sucede un número significativo de veces). Por ejemplo, obtendrá este video [u't.co/LszdhNP '] y devolverá este url etsy.me/r6JBGq, donde realmente necesito la dirección final de youtube a la que se enlaza. ¿Conoces alguna forma de evitar esto? – brandonmat

+2

se hizo un cambio simple en mi respuesta –

2

Tienes que abrirlo, de lo contrario no sabrás a qué URL se redireccionará. Como dijo Greg:

Un enlace corto es la clave de la base de datos de otra persona; no puede expandir el enlace sin consultar la base de datos

Ahora a su pregunta.

¿Alguien sabe de una manera más eficiente para completar esta operación sin usar abrir (ya que es un desperdicio de ancho de banda)?

La manera más eficiente es no cerrar la conexión, mantenerla abierta en segundo plano, mediante el HTTP Connection: keep-alive.

Después de una pequeña prueba, unshorten.me parece tomar el método HEAD en cuenta y hacer una redirección a sí mismo:

> telnet unshorten.me 80 
Trying 64.202.189.170... 
Connected to unshorten.me. 
Escape character is '^]'. 
HEAD http://unshort.me/index.php?r=http%3A%2F%2Fbit.ly%2FcXEInp HTTP/1.1 
Host: unshorten.me 

HTTP/1.1 301 Moved Permanently 
Date: Mon, 22 Aug 2011 20:42:46 GMT 
Server: Microsoft-IIS/6.0 
X-Powered-By: ASP.NET 
X-AspNet-Version: 2.0.50727 
Location: http://resolves.me/index.php?r=http%3A%2F%2Fbit.ly%2FcXEInp 
Cache-Control: private 
Content-Length: 0 

tanto, si utiliza el método HTTP HEAD, en lugar de GET, se quiere en realidad terminan haciendo el mismo trabajo dos veces.

lugar, se debe mantener la conexión viva, lo que le ahorrará sólo un poco ancho de banda, pero lo que se sin duda ahorra es la latencia de establecer una nueva conexión cada vez. El establecimiento de una conexión TCP/IP es caro.

Debería salirse con la suya con varias conexiones mantenidas activas para el servicio de desusar igual a la cantidad de conexiones simultáneas que recibe su propio servicio.

Puede gestionar estas conexiones en un grupo. Eso es lo más cercano que puedes obtener. Junto a la pila de TCP/IP de tweaking your kernel.

+0

Awesome gracias por la información. En este momento voy a utilizar la respuesta de Pedro Loureiro anterior, ya que está funcionando por el momento. Pero me referiré a esto si tengo algún problema. Muy apreciado. – brandonmat

0

pude replicar aquí, pero es probable que sea mejor que apuntar a una página de Inmersión en Python, todo sobre handling redirects , que es exactamente lo que quieres hacer aquí.

10

funciones de una línea, utilizando la biblioteca de solicitudes y sí, admite la recursión.

def unshorten_url(url): 
    return requests.head(url, allow_redirects=True).url 
+0

Creo que esta respuesta es incluso mejor que la respuesta más votada. Pruebe con las URL de fb.net y devuelve la URL correcta, mientras que la otra no hace nada. – lenhhoxung

+0

Este es un trazador de líneas y funciona perfectamente. Probablemente la mejor respuesta. – Aventinus

1

Aquí un código src que tiene en cuenta casi de los casos de esquina útiles:

  • establecer un tiempo de espera personalizado.
  • configura un agente de usuario personalizado.
  • compruebe si tenemos que usar una conexión http o https.
  • resuelven recursivamente la url de entrada y evitan que finalice dentro de un bucle.

El código src está en GitHub @https://github.com/amirkrifa/UnShortenUrl

comentarios son bienvenidos ...

import logging 
logging.basicConfig(level=logging.DEBUG) 

TIMEOUT = 10 
class UnShortenUrl: 
    def process(self, url, previous_url=None): 
     logging.info('Init url: %s'%url) 
     import urlparse 
     import httplib 
     try: 
      parsed = urlparse.urlparse(url) 
      if parsed.scheme == 'https': 
       h = httplib.HTTPSConnection(parsed.netloc, timeout=TIMEOUT) 
      else: 
       h = httplib.HTTPConnection(parsed.netloc, timeout=TIMEOUT) 
      resource = parsed.path 
      if parsed.query != "": 
       resource += "?" + parsed.query 
      try: 
       h.request('HEAD', 
          resource, 
          headers={'User-Agent': 'curl/7.38.0'} 

         ) 
       response = h.getresponse() 
      except: 
       import traceback 
       traceback.print_exec() 
       return url 
      logging.info('Response status: %d'%response.status) 
      if response.status/100 == 3 and response.getheader('Location'): 
       red_url = response.getheader('Location') 
       logging.info('Red, previous: %s, %s'%(red_url, previous_url)) 
       if red_url == previous_url: 
        return red_url 
       return self.process(red_url, previous_url=url) 
      else: 
       return url 
     except: 
      import traceback 
      traceback.print_exc() 
      return None 
Cuestiones relacionadas