棘手的模式匹配

时间:2009-04-23 08:56:17

标签: php regex

这可能很棘手,容易或不可能......我不确定

我有一个域名列表,我试图尽可能地将它们与“title”标签中的网站名称进行匹配。

例如......

Domain: www.yahoo.com 
Title: Yahoo!
Result: Yahoo!

Domain: www.thegreenpages.com 
Title: Welcome to The Green Pages.
Result: The Green Pages

Domain: www.experts-exchange.com:
Title: Experts Exchange - The #1 resource on the web for solving technology problems.
Result: Experts Exchange

所以你可以在这里看到问题。我需要考虑大小写,空格和任何域特殊字符。我还需要捕捉任何特殊字符!在雅虎!但不是像一段句子那样只是句子的结尾和其他你能想到的东西。

有意义吗?

在PHP中。

我真的非常嘲笑这些类型的模式匹配问题:)

6 个答案:

答案 0 :(得分:3)

我不确定你是否会想出一个可以解决所有可能遇到的问题的模式。标题标签可以是完全不匹配的随机文本。

例如,这是一个随机网站,我选择了随机谷歌搜索。网站域名是“plus2net.com”,标题是(显然适用于SEO)“PHP HTML MySQL文章教程,免费脚本和编程论坛”。你会如何关联这两件事?从理论上讲,你可以使用类似levenshtein() function的东西给你一种统计分析,但我认为提出一个正则表达式来解决这个问题是错误的方法。

我会重新思考这个问题。你想达到什么目的?如果您只是想关联域名和标题标签列表,那么您是否可以编写一个快速脚本来从您拥有的域列表中删除标题标签并获取确切数据?

答案 1 :(得分:1)

您可以根据域名构建正则表达式,例如:

t\s*h\s*e\s*g\s*r\s*e\s*e\s*n\s*p\s*a\s*g\s*e\s*s

这将匹配不区分大小写模式中的绿页


编辑以下是如何构建此类正则表达式的示例:

$data = array(
    array('yahoo', 'Yahoo!'),
    array('thegreenpages', 'Welcome to The Green Pages.'),
    array('experts-exchange', 'Experts Exchange - The #1 resource on the web for solving technology problems.')
);

foreach ($data as $item) {
    $domain = preg_split('/(.)/', $item[0], -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
    foreach ($domain as $key => $chr) {
        if ($chr == '-') {
            unset($domain[$key]);
        }
    }
    $pattern = '/'.implode('[\s-]*', $domain).'!?/i';
    preg_match($pattern, $item[1], $match);
    var_dump($match[0]);
}

答案 2 :(得分:1)

试试这段代码:

$sites = array(
    array('domain' => 'www.yahoo.com', 'title' => 'Yahoo!'),
    array('domain' => 'www.thegreenpages.com', 'title' => 'Welcome to The Green Pages.'),
    array('domain' => 'www.experts-exchange.com', 'title' => 'Experts Exchange - The #1 resource on the web for solving technology problems.'),
);

foreach ($sites as $idx => $site) {
    $domain = preg_replace('/^www\./i', '', $site['domain']);
    $domain = preg_replace('/\.(com|net|org|info|us)$/i', '', $domain);

    $expression = '/';
    for ($i = 0; $i < strlen($domain); $i++) {
        $char = $domain[$i];
        $expression .= $char . (ctype_alpha($char) ? '' : '?');
        $expression .= '\s*';
    }
    $expression .= '/i';

    preg_match($expression, $site['title'], $matches);
    $sites[$idx]['name'] = $matches[0];
}

如果你print_r($sites),你会得到:

Array
(
    [0] => Array
        (
            [domain] => www.yahoo.com
            [title] => Yahoo!
            [name] => Yahoo
        )

    [1] => Array
        (
            [domain] => www.thegreenpages.com
            [title] => Welcome to The Green Pages.
            [name] => The Green Pages
        )

    [2] => Array
        (
            [domain] => www.experts-exchange.com
            [title] => Experts Exchange - The #1 resource on the web for solving technology problems.
            [name] => Experts Exchange 
        )
) 

无论你做什么都要调整你的脚本,直到你做对了,但这是一个开始的地方。

答案 3 :(得分:1)

我认为这至少是一个三步过程。

  • 从标题和网址中删除标点符号。
  • 如有必要,请拆分网址。
  • 通过与标题进行比较,使用网址查找正确的案例。
'www.thegreenpages.com'    'Welcome to The Green Pages.'  'The Green Pages'
    'thegreenpages'                                       # remove punctuation
   'the green pages'    <= 'Welcome to The Green Pages'   # split url (if necessary)
                        =>            'The Green Pages'   # result of search

'www.experts-exchange.com'    'Experts Exchange - The #1 res ...'  'Experts Exchange'
    'experts exchange'        'Experts Exchange   The  1 res    '  # remove punctuation
#   'experts exchange'     <= 'Experts Exchange   The  1 res    '  # split url
                           => 'Experts Exchange'                   # result of search

'www.yahoo.com'    'Yahoo!'  'Yahoo!'
    'yahoo'        'Yahoo'   # remove punctuation
#   'yahoo'     <= 'Yahoo'   # split url (if necessary)
                => 'Yahoo'   # result of search
# whoops left off the exclamation point

答案 4 :(得分:0)

除非你严重限制问题域,否则我会说这是不可能的。

title属性可以包含任何人类语言中的任意字符串(符号,外来字符,“智能”内容,您可以命名)。正则表达式如何足够智能以捕捉相关部分?你能用自己的语言正式定义相关部分吗?

当应用于语言时,正则表达式很糟糕,甚至更复杂的系统在应用于人类语言时也会变得很糟糕。

答案 5 :(得分:0)

您的域名列表是否已修复?如果是这样,你可以为每个域构建正则表达式吗?

显然,您可以相当简单地删除域名,但正如Tomalak所说,除非问题域受到更多限制,否则实际上是一个非常复杂的计算问题!

从一个域名中,你需要删除你需要一个参考字典(或每种语言一个)的单词,以及某种单词匹配,也许是对潜在匹配的某种投票。虽然,实际上没有更具体的问题域,但这可能不准确。

了解您想要实现的目标可能会更好吗?