Как надежно извлечь URL-адреса, содержащиеся в URL-адресах, с помощью Python?

Многие поисковые системы отслеживают URL-адреса, по которым был выполнен щелчок, путем добавления URL-адреса результата в строку запроса, которая может принимать следующий формат: http://www.example.com/result?track=http://www.stackoverflow.com/questions/ask

В приведенном выше примере URL-адрес результата является частью строки запроса, но в некоторых случаях он принимает форму http://www.example.com/http://www.stackoverflow.com/questions/ask или используется кодировка URL-адреса.

Подход, который я попробовал первым, - разделить searchengineurl.split("http://"). Некоторые очевидные проблемы с этим:

  • он вернет все части строки запроса, следующие за URL-адресом результата, а не только URL-адрес результата. Это будет проблемой с URL-адресом, подобным этому: http://www.example.com/result?track=http://www.stackoverflow.com/questions/ask&showauthor=False&display=None
  • он не делает различий между какими-либо дополнительными частями строки запроса URL-адреса отслеживания поисковой системы и строки запроса URL-адреса результата. Это может быть проблемой с URL-адресом, подобным этому: http://www.example.com/result?track=http://www.stackoverflow.com/questions/ask?showauthor=False&display=None
  • это не удается, если "http: //" опущено в URL-адресе результата.

Каков наиболее надежный, общий и небезопасный способ извлечения URL-адресов, содержащихся в других URL-адресах, в Python?


person boadescriptor    schedule 24.03.2015    source источник


Ответы (3)


Я бы попробовал использовать urlparse.urlparse, он, вероятно, поможет вам в этом, а небольшая дополнительная работа с вашей стороны даст то, что вы хотите.

person bgm387    schedule 24.03.2015
comment
urlparse.parse_qs было бы полезно? Или вы ищете что-то более надежное? - person bgm387; 24.03.2015

У меня это работает.

from urlparse import urlparse
from urllib import unquote

urls =["http://www.example.com/http://www.stackoverflow.com/questions/ask", 
"http://www.example.com/result?track=http://www.stackoverflow.com/questions/ask&showauthor=False&display=None", 
"http://www.example.com/result?track=http://www.stackoverflow.com/questions/ask?showauthor=False&display=None",
"http://www.example.com/result?track=http%3A//www.stackoverflow.com/questions/ask%3Fshowauthor%3DFalse%26display%3DNonee"]

def clean(url):
    path = urlparse(url).path
    index = path.find("http")
    if not index == -1:
        return path[index:]
    else:
        query = urlparse(url).query
        index = query.index("http")
        query = query[index:]
        index_questionmark = query.find("?")
        index_ampersand = query.find("&")
        if index_questionmark == -1 or index_questionmark > index_ampersand:
            return unquote(query[:index_ampersand])
        else:
            return unquote(query)

for url in urls:
    print clean(url)

> http://www.stackoverflow.com/questions/ask
> http://www.stackoverflow.com/questions/ask
> http://www.stackoverflow.com/questions/ask?showauthor=False&display=None
> http://www.stackoverflow.com/questions/ask?showauthor=False&display=None
person boadescriptor    schedule 10.04.2015

Я не знаю конкретно о Python, но я бы использовал регулярное выражение для получения частей (ключ = значение) строки запроса с чем-то вроде ...

(?:\?|&)[^=]+=([^&]*)

Это отражает "ценностные" части. Затем я бы декодировал их и сравнил их с другим шаблоном (возможно, с другим регулярным выражением), чтобы увидеть, какой из них выглядит как URL-адрес. Я бы просто проверил первую часть, а затем взял бы все значение. Таким образом, ваш шаблон не должен учитывать все возможные типы URL-адресов (и, по-видимому, они не объединяли URL-адрес с чем-то еще в одном поле значения). Это должно работать как с указанным протоколом, так и без него (определение того, как выглядит URL-адрес, зависит от вашего шаблона).

Что касается второго типа URL ... Я не думаю, что есть способ разобрать его без взлома. Вы можете URL-декодировать весь URL-адрес, а затем искать второй экземпляр http: // (или https: // и / или любые другие протоколы, с которыми вы можете столкнуться). Вам нужно будет решить, являются ли какие-либо строки запроса частью «вашего» URL-адреса или URL-адреса трекера. Вы также можете не декодировать URL и попытаться сопоставить закодированные значения. В любом случае будет беспорядочно, а если они не включат протокол, будет еще хуже! Если вы работаете с набором определенных форматов, вы могли бы разработать для них хорошие правила ... но если вам просто нужно справиться с тем, что они случайно бросят в вас ... Я не думаю, что есть надежный способ обрабатывать второй тип встраивания.

person Mike B.    schedule 24.03.2015