Обнаружение (непослушного или приятного) URL или ссылки в текстовой строке - PullRequest
37 голосов
/ 31 марта 2009

Как я могу обнаружить (с помощью регулярных выражений или эвристик) ссылку на веб-сайт в текстовой строке, такой как комментарий?

Цель - предотвратить спам. HTML разорван, поэтому мне нужно обнаружить приглашения для копирования и вставки. Спаммер не должен экономно размещать ссылки, поскольку большинство пользователей не могут успешно попасть на страницу . Я хотел бы получить предложения, ссылки или обсуждение передового опыта.

Некоторые цели:

  • Низко висящие фрукты, такие как правильно сформированные URL (http://some-fqdn/some/valid/path.ext)
  • URL-адреса, но без префикса http:// (т. Е. Действительное полное доменное имя + действительный путь HTTP)
  • Любые другие забавные дела

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

Идеи

Вот некоторые вещи, о которых я думаю.

  • Содержание написано на родном языке, так что я могу быть счастливым при обнаружении
  • Должен ли я сначала убрать все пробелы, чтобы поймать "www .example.com"? Знают ли обычные пользователи, чтобы убрать пространство сами, или сделать какие-либо браузеры «делай, что я имею в виду» и лишить его для вас?
  • Может быть, несколько проходов - лучшая стратегия со сканированием для:
    • Правильно сформированные URL
    • Все не пропуски, за которыми следует '.' сопровождаемый любым действительным ДВУ
    • Что-нибудь еще?

Смежные вопросы

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

Обновление и сводка

Ух ты, здесь есть несколько очень хороших эвристик! Для меня лучшая цена за доллар - это синтез следующего:

  1. @ Техника Джона Брайта по обнаружению ДВУ (хорошая защитная удушающая точка)
  2. Для этих подозрительных строк замените точку символом, похожим на точку, в соответствии с @ capar
  3. Хороший персонаж, похожий на точку, это @ Sharkey's subspted & middot; (т.е. " & middot; "). & Мидот; также является границей слова, поэтому сложнее случайно скопировать и вставить.

Это должно сделать CPM спаммера достаточно низким для моих нужд; обратная связь «пометить как неприемлемую» должна отразить все остальное. Другие перечисленные решения также очень полезны:

  • Удалите все пунктирные квадраты (@ комментарий Шарки к его собственному ответу)
  • @ Требование Sporkmonger для клиентского Javascript, который вставляет в форму обязательное скрытое поле.
  • Пингуйте URL-адрес на стороне сервера, чтобы определить, является ли он веб-сайтом. (Возможно, я мог бы запустить HTML через SpamAssassin или другой байесовский фильтр согласно @Nathan ..)
  • Посмотрите на источник Chrome для его умной адресной строки, чтобы увидеть, какие хитрые трюки использует Google
  • Обращение к OWASP AntiSAMY или другим веб-службам для обнаружения спама / вредоносного ПО.

Ответы [ 13 ]

19 голосов
/ 15 апреля 2009

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

Я думаю, что ваша лучшая ставка будет на ДВУ. Существуют двухбуквенные нДВУ и сравнительно небольшой список (в настоящее время). Они должны начинаться с точки или с суффикса или какой-либо границы слова. Как отметили другие, это не будет идеальным. Нет никакого способа получить «покупать забавные фармацевтические препараты. Это», не отказываясь от законного «я попробовал снова. Это не работает» или подобного. Все это сказал, это было бы мое предложение:

[^\b]\.([a-zA-Z]{2}|aero|asia|biz|cat|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel)[\b/]

Вещи, которые это получит:

Это, конечно, сломается, как только люди начнут запутывать свои URL, заменяя "." с "точкой". Но, опять же, если предположить, что ваша цель - спамеры, если они начнут делать подобные вещи, их рейтинг кликов упадет еще на пару порядков до нуля. Множество людей, достаточно информированных, чтобы деобфусцировать URL, и множество людей, недостаточно информированных, чтобы посещать спам-сайты, я думаю, имеет крошечное пересечение. Это решение должно позволить вам обнаруживать все URL-адреса, которые можно копировать и вставлять в адресную строку, сохраняя при этом побочный ущерб на минимальном уровне.

13 голосов
/ 31 марта 2009
6 голосов
/ 15 апреля 2009

Я знаю, что это не помогает с текстом автоматической ссылки, но что если вы будете искать и заменять все точки полного останова символом, который выглядит как одно и то же, например символом юникода для точки иврита hiriq (U + 05B4 )?

Следующий абзац является примером:

Это может сработать ִ Период выглядит немного странно, но все еще читаемо ִ Преимущество, конечно, в том, что любой, кто копирует и вставляет www ִ google ִ com, не зайдет слишком далеко ִ:)

6 голосов
/ 14 апреля 2009

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

Если ваша цель - просто отфильтровывать спам из комментариев, то вы можете подумать о байесовской фильтрации. Он очень точно пометил электронную почту как спам, возможно, он сможет сделать то же самое и для вас, в зависимости от объема текста, который вам нужно отфильтровать.

4 голосов
/ 15 апреля 2009

Ну, очевидно, низко висящие фрукты - это вещи, которые начинаются с http: // и www. Попытка отфильтровать такие вещи, как «www. G mail. Com», приводит к интересным философским вопросам о том, как далеко вы хотите зайти. Вы хотите сделать следующий шаг и отфильтровать «www dot gee mail dot com»? Как насчет абстрактных описаний URL, таких как «Аббревиатура для всемирной паутины, за которой следует точка, за которой следует буква g, за которой следует слово mail, за которым следует точка, заканчивающаяся аббревиатурой TLD для коммерческого использования».

Важно провести черту, какие вещи вы собираетесь пытаться отфильтровать, прежде чем продолжать пытаться разработать свой алгоритм. Я думаю, что линия должна быть проведена на уровне, где «gmail.com» считается URL, а «gmail.com» - нет. В противном случае вы, вероятно, получите ложные срабатывания каждый раз, когда кто-то не сможет использовать первую букву в предложении.

3 голосов
/ 15 апреля 2009

Поскольку вы в первую очередь ищете приглашения для копирования и вставки в адресную строку браузера, возможно, стоит взглянуть на код, используемый в браузерах с открытым исходным кодом (например, Chrome или Mozilla), чтобы решить, вводится ли текст в «эквивалент адресной строки» - это поисковый запрос или попытка перехода по URL.

2 голосов
/ 18 апреля 2009

Пинг возможного URL

Если вы не возражаете против небольшого вычисления на стороне сервера, как насчет этого?

urls = []
for possible_url in extracted_urls(comment):
    if pingable(possible_url):
       urls.append(url)  #you could do this as a list comprehension, but OP may not know python

Здесь:

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

  2. pingable фактически использует системный вызов, чтобы определить, существует ли имя хоста в сети. Вы могли бы иметь простую оболочку для анализа вывода ping.

    [ramanujan: ~ / base] $ ping -c 1 www.google.com

    PING www.l.google.com (74.125.19.147): 56 байтов данных 64 байта из 74.125.19.147: icmp_seq = 0 ttl = 246 время = 18,317 мс

    --- www.l.google.com статистика пинга --- 1 пакет передан, 1 пакет получен, 0% потеря пакета туда-обратно min / avg / max / stddev = 18,317 / 18,317 / 18,317 / 0,000 мс

    [ramanujan: ~ / base] $ ping -c 1 fooalksdflajkd.com

    ping: не удается разрешить fooalksdflajkd.com: Неизвестный хост

Недостатком является то, что если хост выдаст 404, вы его не обнаружите, но это довольно неплохой первый шаг - лучший способ проверить, является ли адрес веб-сайта, - попытаться перейти на него. Вы также можете попробовать wget'ing этот URL, но это более тяжелый вес.

1 голос
/ 19 апреля 2009

Здесь уже есть несколько отличных ответов, поэтому я не буду больше публиковать. Я дам пару ошибок, хотя. Во-первых, обязательно проверьте на известные протоколы, все остальное может быть непослушным Как человек, чье хобби связано с ссылками telnet, вы, вероятно, захотите включить в поиск больше, чем http (s), но, возможно, захотите запретить, например, цель: или некоторые другие URL-адреса. Во-вторых, многие люди разграничивают свои ссылки в угловых скобках (gt / lt), таких как <<a href="http://theroughnecks.net" rel="nofollow noreferrer">http://theroughnecks.net> или в скобках "(url)", и нет ничего хуже, чем щелкнуть ссылку и получить закрывающую> или ) идти вместе с остальной частью URL.

P.S. извините за самореферентные штекеры;)

1 голос
/ 19 апреля 2009

Мне нравится ответ capar лучший на данный момент, но иметь дело со шрифтами Unicode может быть немного чревато, так как старые браузеры часто показывают забавную вещь или маленькую коробочку ... и расположение U + 05B4 немного странно ... для меня это выглядит вне каналов здесь | & # x05b4; | хотя это между ними.

Есть удобный & миддот; (& middot;), хотя, который разбивает вырезать и вставить таким же образом. Его вертикальное выравнивание можно исправить с помощью , например:

StackOverflow & Мидот; 1010 * ком *

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

Точки, которых нет в подозрительных URL, могут быть оставлены в покое, так что, например, вы можете сделать

s/\b\.\b/<sub>&middot;<\/sub>/g

Другой вариант - вставить некую сущность нулевой ширины рядом с подозрительными точками, но такие вещи, как & zwj; и & zwnj; и & ampzwsp; не похоже на работу в FF3.

1 голос
/ 18 апреля 2009

Рассмотрите возможность использования OWASP AntiSAMY API ...

...