Как определить регулярное выражение для удаления текстовых спам-ссылок («spam1 dot com») из строки Java? - PullRequest
5 голосов
/ 10 октября 2011

У меня есть список сайтов, которые представляют спам-ссылки:

List<String> bannedSites = ["spam1.com", "spam2.com", "spam3.com"];

Существует ли регулярный способ удаления ссылок, соответствующих этим запрещенным сайтам, из этого текста:

Dear Arezzo,
Please check out my website at spam1.com or http://www.spam1.com 
or http://spam1.com or spam1 dot com to win millions of dollars in prizes.
Thank you.
Big Spammer

Обратите внимание, что ссылка может иметь несколько форматов URL, которые aioobe 's решение хорошо идентифицирует:

    String input = "Dear Arezzo,\n"
        + "Please check out my website at spam1.com or http://www.spam1.com" 
        + "or http://spam1.com or spam1 dot com to win millions of dollars in prizes."
        + "Thank you.";

    List<String> bannedSites = Arrays.asList("spam1.com", "spam2.com", "spam3.com");

    StringBuilder re = new StringBuilder();
    for (String bannedSite : bannedSites) {
        if (re.length() > 0)
            re.append("|");
        re.append(String.format("http://(www\\.)?%s\\S*|%1$s",
                                Pattern.quote(bannedSite)));
    }

    System.out.println(input.replaceAll(re.toString(), "LINK REMOVED"));

Но хотя приведенный выше код отлично работает для форматов URL spam1.com или http://www.spam1.com или http://spam1.com, он пропускает несколько текстовых форматов:

Как я могу изменить регулярное выражение для целевых текстовых форматов, таких как эти?

spam1 dot com
spam1[.com]
spam1 .com
spam1 . com

Идея состоит в том, чтобы получить такой результат:

Dear Arezzo,
Please check out my website at [LINK REMOVED] or [LINK REMOVED] 
or [LINK REMOVED] or [LINK REMOVED] to win millions of dollars in prizes.
Thank you.
Big Spammer

Как я заметил в комментариях ниже, мне, вероятно, не нужно запрещать всю строку spam1 dot com. Если бы я мог стереть только часть spam1, чтобы она стала: [LINK REMOVED] dot com - это сделало бы эту работу.

Ответы [ 3 ]

2 голосов
/ 10 октября 2011

Вот вам начало.

import java.util.*;
import java.util.regex.Pattern;

class Test {
    public static void main(String[] args) {

        String input = "Dear Arezzo,\n"
            + "Please check out my website at spam1.com "
            + "or http://www.spam1.com or http://spam1.com or " 
            + "spam1 dot com to win millions of dollars in prizes.\n"
            + "Thank you.";

        List<String> bannedSites = Arrays.asList("spam1", "spam2", "spam3");

        StringBuilder re = new StringBuilder();
        for (String bannedSite : bannedSites) {
            if (re.length() > 0)
                re.append("|");
            String quotedSite = Pattern.quote(bannedSite);
            re.append("https?://(www\\.)?" + quotedSite + "\\S*");
            re.append("|" + quotedSite + "\\s*(dot|\\.)?\\s*(com|net|org)");
            //re.append("|" ... your variation here);
        }

        System.out.println(input.replaceAll(re.toString(), "LINK REMOVED"));
    }
}

Вывод:

Уважаемый Ареццо,

Пожалуйста, посетите мой сайт по адресуLINK REMOVED или LINK REMOVED или LINK REMOVED или LINK REMOVED, чтобы выиграть миллионы долларов в призах.Спасибо.

Расширьте регулярное выражение при необходимости.

0 голосов
/ 10 октября 2011

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

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

final String[] spam = new String[] {"spam1.com", "spam2.net"};
System.out.println("***** SPAM SITES *****\n" + Arrays.toString(spam)
        + "\n");
final StringBuilder patternBuilder = new StringBuilder();
patternBuilder.append("(?i)(?:(?:f|ht)tps?://)?(?:\\S*?)(");
for (final String s : spam) {
    patternBuilder
            .append("(?:\\[|\\])?"
                    + s.replaceAll("\\.",
                            "\\\\s*(?:\\\\[|\\\\])?\\\\s*(?:\\\\.|dot)\\\\s*(?:\\\\[|\\\\])?\\\\s*")
                    + "\\s*(?:\\[|\\])?").append("|");
}
patternBuilder.setLength(patternBuilder.length() - 1);
patternBuilder.append(")(?:/\\S*)?(?=\\s|$)");
final String ps = patternBuilder.toString();
final String psLong = ps;
System.out.println("***** PATTERN *****\n" + psLong + "\n");
final Pattern p = Pattern.compile(ps);
for (String s : new String[] {"http://www.spam1.com",
        "http://spam2.net", "www.spam1.com", "spam1 dot com",
        "spam1[.com]", "spam1 .com", "spam2 . net", "no links here"})
{
    final Matcher m = p.matcher(s);
    if (m.matches()) {
        System.out.println("Success: " + s);
    } else {
        System.out.println("Fail: " + s);
    }
}
final String message =
        "Dear Arezzo,\nPlease check out my website at spam1.com or http://www.spam1.com \nor http://spam1.com or spam1 dot com to win millions of dollars in prizes.\nThank you.\nBig Spammer\n";
final Matcher m = p.matcher(message);
System.out.println("\n\n***** ORIGINAL MESSAGE *****\n" + message
        + "\n\n***** REPLACED LINKS *****\n"
        + m.replaceAll("[LINK REMOVED]"));

Какие выходы:

***** SPAM SITES *****
[spam1.com, spam2.net]

***** PATTERN *****
(?i)(?:(?:f|ht)tps?://)?(?:\S*?)((?:\[|\])?spam1\s*(?:\[|\])?\s*(?:\.|dot)\s*(?:\[|\])?\s*com\s*(?:\[|\])?|(?:\[|\])?spam2\s*(?:\[|\])?\s*(?:\.|dot)\s*(?:\[|\])?\s*net\s*(?:\[|\])?)(?:/\S*)?(?=\s|$)

Success: http://www.spam1.com
Success: http://spam2.net
Success: www.spam1.com
Success: spam1 dot com
Success: spam1[.com]
Success: spam1 .com
Success: spam2 . net
Fail: no links here


***** ORIGINAL MESSAGE *****
Dear Arezzo,
Please check out my website at spam1.com or http://www.spam1.com 
or http://spam1.com or spam1 dot com to win millions of dollars in prizes.
Thank you.
Big Spammer


***** REPLACED LINKS *****
Dear Arezzo,
Please check out my website at [LINK REMOVED] or [LINK REMOVED]
or [LINK REMOVED] or [LINK REMOVED] to win millions of dollars in prizes.
Thank you.
Big Spammer
0 голосов
/ 10 октября 2011

Я предлагаю использовать TRIE (http://en.wikipedia.org/wiki/Trie) DS для хранения черного списка веб-сайтов. Теперь, читая веб-сайт, вы можете сделать сравнение и удалить запрещенные сайты. Это будет эффективнее, чем регулярное выражение, так как с помощью регулярного выражения вы будете искатьза каждую строку спам-сайта во входном тексте.

...