Как извлечь URL-адрес из строки с помощью Python?

Например:

string = "This is a link http://www.google.com"

Как я могу извлечь "http://www.google.com"?

(Каждая ссылка будет иметь тот же формат, то есть «http: //»)


person Sheldon    schedule 18.03.2012    source источник
comment
Вы можете проверить этот ответ: stackoverflow.com/questions/499345/   -  person rjz    schedule 18.03.2012
comment
Когда я пробую это решение, ничего не возвращается.   -  person Sheldon    schedule 18.03.2012
comment
Если это необработанный текстовый файл (как указано в вашем вопросе), вы можете проверить этот ответ: stackoverflow.com/questions/839994/extracting-a-url-in-python   -  person Alexandre Dulaunoy    schedule 18.03.2012
comment
См. mathiasbynens.be/demo/url-regex.   -  person Martin Thoma    schedule 17.08.2017


Ответы (5)


arrow_upward
34
arrow_downward

Для этого может быть несколько способов, но самым чистым было бы использовать регулярное выражение.

>>> myString = "This is a link http://www.google.com"
>>> print re.search("(?P<url>https?://[^\s]+)", myString).group("url")
http://www.google.com

Если может быть несколько ссылок, вы можете использовать что-то похожее на приведенное ниже

>>> myString = "These are the links http://www.google.com  and http://stackoverflow.com/questions/839994/extracting-a-url-in-python"
>>> print re.findall(r'(https?://[^\s]+)', myString)
['http://www.google.com', 'http://stackoverflow.com/questions/839994/extracting-a-url-in-python']
>>>
person Abhijit    schedule 18.03.2012
comment
Это слишком грубо для многих реальных сценариев. Он полностью не работает для ftp:// URL-адресов, mailto: URL-адресов и т. Д. И наивно берет хвостовую часть из <a href="http://google.com/">Click here</a> (т. Е. Вверх через клик). - person tripleee; 10.10.2014
comment
@tripleee Вопрос не в синтаксическом анализе HTML, а в поиске URL-адреса в строке текста, который всегда будет иметь формат http. Так что это действительно хорошо работает. Но да, очень важно, чтобы люди знали, что вы говорите, если они здесь для синтаксического анализа HTML или чего-то подобного. - person teewuane; 16.11.2016

arrow_upward
23
arrow_downward

Чтобы найти веб-URL в общей строке, вы можете использовать регулярное выражение (regex).

Простое регулярное выражение для сопоставления URL-адресов, подобное приведенному ниже, должно соответствовать вашему случаю.

    regex = r'('

    # Scheme (HTTP, HTTPS, FTP and SFTP):
    regex += r'(?:(https?|s?ftp):\/\/)?'

    # www:
    regex += r'(?:www\.)?'

    regex += r'('

    # Host and domain (including ccSLD):
    regex += r'(?:(?:[A-Z0-9][A-Z0-9-]{0,61}[A-Z0-9]\.)+)'

    # TLD:
    regex += r'([A-Z]{2,6})'

    # IP Address:
    regex += r'|(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})'

    regex += r')'

    # Port:
    regex += r'(?::(\d{1,5}))?'

    # Query path:
    regex += r'(?:(\/\S+)*)'

    regex += r')'

Если вы хотите быть еще более точным, в разделе TLD вы должны убедиться, что TLD является действительным TLD (см. Полный список действительных TLD здесь: https://data.iana.org/TLD/tlds-alpha-by-domain.txt):

    # TLD:
    regex += r'(com|net|org|eu|...)'

Затем вы можете просто скомпилировать бывшее регулярное выражение и использовать его для поиска возможных совпадений:

    import re

    string = "This is a link http://www.google.com"

    find_urls_in_string = re.compile(regex, re.IGNORECASE)
    url = find_urls_in_string.search(string)

    if url is not None and url.group(0) is not None:
        print("URL parts: " + str(url.groups()))
        print("URL" + url.group(0).strip())

Что в случае строки "Это ссылка http://www.google.com" выведет:

    URL parts: ('http://www.google.com', 'http', 'google.com', 'com', None, None)
    URL: http://www.google.com

Если вы измените ввод более сложным URL-адресом, например "Это также URL-адрес https://www.host.domain.com:80/path/page.php?query=value&a2=v2#foo, но этого больше нет" вывод будет:

    URL parts: ('https://www.host.domain.com:80/path/page.php?query=value&a2=v2#foo', 'https', 'host.domain.com', 'com', '80', '/path/page.php?query=value&a2=v2#foo')
    URL: https://www.host.domain.com:80/path/page.php?query=value&a2=v2#foo

ПРИМЕЧАНИЕ. Если вы ищете больше URL-адресов в одной строке, вы все равно можете использовать то же регулярное выражение, но просто findall () вместо search ().

person Paolo Rovelli    schedule 11.08.2015
comment
Итак, регулярное выражение оказывается ((?:(https?|s?ftp):\/\/)?(?:www\.)?((?:(?:[A-Z0-9][A-Z0-9-]{0,61}[A-Z0-9]\.)+)([A-Z]{2,6})|(?:\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}))(?::(\d{1,5}))?(?:(\/\S+)*)). Также обратите внимание, что список TLD прямо сейчас также включает забавные окончания, такие как XN--VERMGENSBERATUNG-PWB, состоящий из 24 символов, который не будет пойман этим. - person luckydonald; 21.09.2016
comment
Лучше бы к выкройке добавить (?i) - более переносимо. Также имейте в виду, что это будет соответствовать 23.084.828.566, который не является допустимым IP-адресом, но является допустимым числом с плавающей запятой в некоторых регионах. - person Mr_and_Mrs_D; 01.03.2018
comment
У этого регулярного выражения есть какое-то ограничение на длину, например: docs.google.com/spreadsheets/d/10FmR8upvxZcZE1q9n1o40z16mygUJklkXQ7lwGS4nlI просто соответствует docs.google.com/spreadsheets/d/10FmR8upvxZcZE1q9n. - person Jorge Orpinel Pérez; 25.10.2018

arrow_upward
15
arrow_downward

Есть еще один способ легко извлечь URL-адреса из текста. Вы можете использовать urlextract, чтобы сделать это за вас, просто установите его через pip:

pip install urlextract

а затем вы можете использовать это так:

from urlextract import URLExtract

extractor = URLExtract()
urls = extractor.find_urls("Let's have URL stackoverflow.com as an example.")
print(urls) # prints: ['stackoverflow.com']

Дополнительную информацию можно найти на моей странице github: https://github.com/lipoja/URLExtract

ПРИМЕЧАНИЕ. Чтобы держать вас в курсе, он загружает список TLD с iana.org. Но если у программы нет доступа в Интернет, то она не для вас.

person Community    schedule 15.02.2017
comment
Работает как шарм и не загромождает остальную часть моего сценария. - person Henrik; 30.08.2020

arrow_upward
6
arrow_downward

Это извлекает все URL-адреса с параметрами, почему-то все приведенные выше примеры не сработали для меня.

import re

data = 'https://net2333.us3.list-some.com/subscribe/confirm?u=f3cca8a1ffdee924a6a413ae9&id=6c03fa85f8&e=6bbacccc5b'

WEB_URL_REGEX = r"""(?i)\b((?:https?:(?:/{1,3}|[a-z0-9%])|[a-z0-9.\-]+[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)/)(?:[^\s()<>{}\[\]]+|\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\))+(?:\([^\s()]*?\([^\s()]+\)[^\s()]*?\)|\([^\s]+?\)|[^\s`!()\[\]{};:'".,<>?«»“”‘’])|(?:(?<!@)[a-z0-9]+(?:[.\-][a-z0-9]+)*[.](?:com|net|org|edu|gov|mil|aero|asia|biz|cat|coop|info|int|jobs|mobi|museum|name|post|pro|tel|travel|xxx|ac|ad|ae|af|ag|ai|al|am|an|ao|aq|ar|as|at|au|aw|ax|az|ba|bb|bd|be|bf|bg|bh|bi|bj|bm|bn|bo|br|bs|bt|bv|bw|by|bz|ca|cc|cd|cf|cg|ch|ci|ck|cl|cm|cn|co|cr|cs|cu|cv|cx|cy|cz|dd|de|dj|dk|dm|do|dz|ec|ee|eg|eh|er|es|et|eu|fi|fj|fk|fm|fo|fr|ga|gb|gd|ge|gf|gg|gh|gi|gl|gm|gn|gp|gq|gr|gs|gt|gu|gw|gy|hk|hm|hn|hr|ht|hu|id|ie|il|im|in|io|iq|ir|is|it|je|jm|jo|jp|ke|kg|kh|ki|km|kn|kp|kr|kw|ky|kz|la|lb|lc|li|lk|lr|ls|lt|lu|lv|ly|ma|mc|md|me|mg|mh|mk|ml|mm|mn|mo|mp|mq|mr|ms|mt|mu|mv|mw|mx|my|mz|na|nc|ne|nf|ng|ni|nl|no|np|nr|nu|nz|om|pa|pe|pf|pg|ph|pk|pl|pm|pn|pr|ps|pt|pw|py|qa|re|ro|rs|ru|rw|sa|sb|sc|sd|se|sg|sh|si|sj|Ja|sk|sl|sm|sn|so|sr|ss|st|su|sv|sx|sy|sz|tc|td|tf|tg|th|tj|tk|tl|tm|tn|to|tp|tr|tt|tv|tw|tz|ua|ug|uk|us|uy|uz|va|vc|ve|vg|vi|vn|vu|wf|ws|ye|yt|yu|za|zm|zw)\b/?(?!@)))"""
re.findall(WEB_URL_REGEX, text)
person Artem Bernatskyi    schedule 28.05.2018

arrow_upward
4
arrow_downward

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

1.

>>> import re
>>> string = "This is a link http://www.google.com"
>>> pattern = r'[(http://)|\w]*?[\w]*\.[-/\w]*\.\w*[(/{1})]?[#-\./\w]*[(/{1,})]?'
>>> re.search(pattern, string)
http://www.google.com

>>> TWEET = ('New Pybites article: Module of the Week - Requests-cache '
         'for Repeated API Calls - http://pybit.es/requests-cache.html '
         '#python #APIs')
>>> re.search(pattern, TWEET)
http://pybit.es/requests-cache.html

>>> tweet = ('Pybites My Reading List | 12 Rules for Life - #books '
             'that expand the mind! '
             'http://pbreadinglist.herokuapp.com/books/'
             'TvEqDAAAQBAJ#.XVOriU5z2tA.twitter'
             ' #psychology #philosophy')
>>> re.findall(pattern, TWEET)
['http://pbreadinglist.herokuapp.com/books/TvEqDAAAQBAJ#.XVOriU5z2tA.twitter']

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

2.

>>> pattern = r'[(http://)|\w]*?[\w]*\.[-/\w]*\.\w*[(/{1})]?[#-\./\w]*[(/{1,})]?|#[.\w]*'
>>> re.findall(pattern, tweet)
['#books', http://pbreadinglist.herokuapp.com/books/TvEqDAAAQBAJ#.XVOriU5z2tA.twitter', '#psychology', '#philosophy']

Приведенный выше пример получения URL-адреса и хэштегов можно сократить до

>>> pattern = r'((?:#|http)\S+)'
>>> re.findall(pattern, tweet)
['#books', http://pbreadinglist.herokuapp.com/books/TvEqDAAAQBAJ#.XVOriU5z2tA.twitter', '#psychology', '#philosophy']

Приведенный ниже шаблон может соответствовать двум буквенно-цифровым значениям, разделенным знаком. как URL

>>> pattern = pattern =  r'(?:http://)?\w+\.\S*[^.\s]'

>>> tweet = ('PyBites My Reading List | 12 Rules for Life - #books '
             'that expand the mind! '
             'www.google.com/telephone/wire....  '
             'http://pbreadinglist.herokuapp.com/books/'
             'TvEqDAAAQBAJ#.XVOriU5z2tA.twitter '
             "http://-www.pip.org "
             "google.com "
             "twitter.com "
             "facebook.com"
             ' #psychology #philosophy')
>>> re.findall(pattern, tweet)
['www.google.com/telephone/wire', 'http://pbreadinglist.herokuapp.com/books/TvEqDAAAQBAJ#.XVOriU5z2tA.twitter', 'www.pip.org', 'google.com', 'twitter.com', 'facebook.com']

Вы можете попробовать любой сложный URL с шаблоном номера 1 и 2. Чтобы узнать больше о модуле re в Python, ознакомьтесь с РЕГЕКСАМИ В PYTHON от Real Python.

Ваше здоровье!

person Comsavvy    schedule 25.10.2020