Как я могу сократить URL-адрес с помощью Python? - PullRequest
6 голосов
/ 23 августа 2011

Я уже видел эту тему - Как я могу удалить URL-адрес?

Моя проблема с разрешенным ответом (который использует API unshort.me) заключается в том, что я сосредоточен на сокращении ссылок на YouTube. Так как unshort.me используется легко, это возвращает почти 90% результатов с капчами, которые я не могу определить.

Пока я застрял с использованием:

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

Примечание: все в комментариях - это то, что я пытался сделать, используя сервис unshort.me, который возвращал ссылки с картинки.

Кто-нибудь знает о более эффективном способе выполнения этой операции без использования open (поскольку это трата пропускной способности)?

Ответы [ 4 ]

15 голосов
/ 23 августа 2011

Используйте лучший ответ (не принятый ответ) в этом вопросе:

# 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
13 голосов
/ 10 мая 2015

однострочные функции с использованием библиотеки запросов и да, она поддерживает рекурсию.

def unshorten_url(url):
    return requests.head(url, allow_redirects=True).url
2 голосов
/ 23 августа 2011

Вам НУЖНО открыть его, иначе вы не будете знать, на какой URL он будет перенаправлен.Как сказал Грег:

Короткая ссылка - это ключ к чужой базе данных;Вы не можете расширить ссылку, не запросив базу данных

Теперь к вашему вопросу.

Кто-нибудь знает о более эффективном способе выполнения этой операции без использования open (поскольку это бесполезная трата пропускной способности)?

Более эффективный способ - не закрывать соединение, оставьте его открытым в фоновом режиме, используя HTTP Connection: keep-alive.

.Небольшой тест unshorten.me, похоже, учитывает метод HEAD и выполняет перенаправление на себя:

> 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

Так что если вы используете метод HEAD HTTP вместо GET, вы на самом деле будете выполнять одну и ту же работу дважды .

Вместо этого вы должны поддерживать соединение живым, что сэкономит вам лишь небольшую пропускную способность, но то, что оно будет безусловно, экономит задержка при установлении нового соединения каждый раз.Установление TCP / IP-соединения стоит дорого .

Вам должно быть предоставлено количество поддерживаемых соединений с несжатым сервисом, равное количеству одновременных соединений, которые получает ваш собственный сервис.

Вы можете управлять этими соединениями в пуле.Это самое близкое, что вы можете получить.Помимо настройка вашего ядра стека TCP / IP.

1 голос
/ 16 июля 2015

Вот код src, который учитывает почти все полезные случаи:

  • установить пользовательское время ожидания.
  • установить пользовательский агент пользователя.
  • проверьте, нужно ли нам использовать соединение http или https.
  • рекурсивно разрешить входной URL и предотвратить завершение внутри цикла.

Код src находится на github @ https://github.com/amirkrifa/UnShortenUrl

комментарии приветствуются ...

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