Regex, чтобы найти все URL в строке, которая содержит подстроку И не содержит другую - PullRequest
0 голосов
/ 04 февраля 2020

Мне удалось отфильтровать все URL из этой строки:

hi, this is your link (but this one is bad formatted and useless):

https://www.test.comhttps://app.test.com/a/b/c/5e20bed422e7880012ba8acc/next?param=1?locale=2

but there is a good link too:

https://app.test.com/a/b/c/5e20bed422e7880012ba8acc/next?param=1?locale=2

and there are also other irrelevant links:

http://www.google.com
http://test.test.com

с этим RegEx

http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+

Поработав некоторое время, я застрял, пытаясь понять как его настроить и получить только:

https://www.test.com/a/b/c/5e20bed422e7880012ba8acc/next?param=1?locale=2

Какой самый простой способ отфильтровать URL, содержащие '/ next?' но не 'comhttps'?

спасибо большое!

Ответы [ 2 ]

1 голос
/ 04 февраля 2020

Использование:

\bhttps?://(?=[\w.]*/)(?:(?!https?://).)*

Он находит правильный URL и отклоняет другие из вашего примера.

Демонстрация и объяснение


import re

body_text = '''
hi, this is your link (but this one is bad formatted and useless):

https://www.test.comhttps://app.test.com/a/b/c/5e20bed422e7880012ba8acc/next?param=1?locale=2

but there is a good link too:

https://app.test.com/a/b/c/5e20bed422e7880012ba8acc/next?param=1?locale=2

and there are also other irrelevant links:

http://www.google.com
http://test.test.com
'''
url = re.findall(r"\bhttps?://(?=[\w.]*/)(?:(?!https?://).)*", body_text)
print url

Выход:

['https://app.test.com/a/b/c/5e20bed422e7880012ba8acc/next?param=1?locale=2']
1 голос
/ 04 февраля 2020

Как насчет этого?

(https?:\/\/[a-z0-9]+(?:[\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6})(?=https?)(\S+)

Мы будем использовать флаг i для поиска без учета регистра.

Протестируйте его здесь: https://regex101.com/r/J62XZq/2

Пояснение

  • https?:\/\/ предназначено для поиска http: // или https: //

  • [a-z0-9]+(?:[\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6} - поиск действительного доменного имени. Я не проверял, действительно ли это было полностью пуленепробиваемым. Но, похоже, неплохо. Мы могли бы найти официальное регулярное выражение для проверки доменных имен. Группа (?:) - это группа без захвата (если она нам не нужна).

  • (https?:\/\/[a-z0-9]+(?:[\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}) оба вместе и включены в группу, так что у нас есть оригинал URL.

  • (?=https?) - это позитивный прогноз, поэтому перед доменом должны следовать http или https. Возможно, вам придется адаптировать его, если у вас есть ftp или другие протоколы.

  • (\S+) предназначен для сопоставления непробельных символов один или несколько раз и захвата его в группе (для дальнейшего использования и обработка. Эта вторая группа должна быть обработана, чтобы избавиться от второй строки запроса ?param=x&option, которая, вероятно, принадлежит окружающему URL.

Редактировать

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

https://regex101.com/r/J62XZq/7

Здесь мы ищем URL с доменом, за которым не следует http: или https:.

Хитрость заключается в добавлении \b в начале, чтобы избежать сопоставление URL-адреса внутри URL-адреса и использование отрицательного просмотра после домена.

\bhttps?:\/\/[a-z0-9]+(?:[\-\.]{1}[a-z0-9]+)*\.[a-z]{2,6}(?!https?:)\/\S+\/next\?(\S+)

Отрицательный просмотр выполняется с помощью (?!https?:) (я не добавил двойной sla sh, так как я предполагаю, что это достаточно).

Последняя часть с /next может не это необходимо. Это зависит от того, хотите ли вы точно сопоставить URL-адрес с внутренним или нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...