【问题标题】:parsing text for contents of database table of limited size为有限大小的数据库表的内容解析文本
【发布时间】:2011-01-12 16:46:59
【问题描述】:

我有一个“人”的 MySQL 表作为网站的一部分,例如:

| people_id |名字 |姓氏 | ----------------------------------------- | 1 |约翰 |列侬 | | 2 |保罗 |麦卡特尼 | | 3 |乔治 |哈里森 | | 4 |林戈 |斯塔尔 | | . | . | . |

我的表大约有 2000 行。

我在网站上还有一个“新闻”部分。通常,这些新闻项目包含对“人”的引用,例如

约翰列侬和保罗麦卡特尼写道 一些最流行的歌曲在 摇滚音乐的历史。

是否可以(或合理/可取)自动解析每条新闻以查找数据库中的“人”,然后将它们转换为链接。因此,例如,上面的文本将变成这样(或功能等效的东西):

<a href="/people/1>John Lennon</a> and <a href="/people/2">Paul McCartney</a> wrote some of the most popular songs in the history of rock music.

最好的方法是什么?我在 php 中使用正则表达式进行了一些失败的尝试,但我想这不是最好的方法。我对 javascript(及其框架)了解不多,但如果这样做有意义,我会很乐意使用它。

这不是网站的基本功能(但我觉得这是一个很好的补充),所以我宁愿省略这样的功能,而不是大幅增加页面加载时间。

编辑

我在最初的问题中省略了一些细节,以缩短篇幅。

事实上,它是一个足球俱乐部的网站——所有“人”都是该网站的成员,可以登录、添加和编辑新闻报道(例如,比赛报道),他们在其中经常提到其他“人”。所以添加新闻报道的不只是我 - (大约)2000 名其他用户可以添加它们。

虽然会员资格有一定的限制,必须先获得批准才能加入,但系统必须能够处理复杂的问题,例如名字不寻常的人,并且有几个人同名的情况.

我已经实现了一种解决方案,其中我使用一种专有代码来标记人们的名字(例如 [p=1]John Lennon[/p]),但我发现,在 2000该网站的用户,只有少数人使用它。

值得一提的是,该网站是 www.ouafc.com,而新闻报道的例子是 www.ouafc.com/news/312。

【问题讨论】:

  • 这可能很棘手 - 例如,您将如何处理“约翰列侬基金会”?仅链接名称可能看起来仍然像您打算链接到基金会...
  • @OrbMan,即使在那种情况下(虽然我完全理解这一点,但不要误会我的意思),只要它引用相同的 John Lennon 它仍然是正确的。取决于实现,如果链接是从 John 的开头然后是 Lennon 的,只要 Foundation 部分没有与它。
  • 技术上正确,但可用性受到影响。另一个极端情况是子字符串匹配,您同时拥有 John SmithJohn Smith Jones 用户 - 您必须注意双嵌入链接情况。
  • 对我来说听起来是个有趣的想法。由于您可能控制了数据库,我相信您可以找到处理潜在名称冲突的方法,例如 John Smith 示例。我假设该网站的内容相当具体,所以人们应该知道,如果有一个链接指向一个名叫约翰列侬的总统竞选人,那可能不是来自......它是什么......猴子? ;o)
  • 对于某些问题,一种可能的解决方法是使用正则表达式来检查相邻单词的大小写,这样如果 'Jones' 出现在它之后,'John Smith' 就不会收到链接,而 'John如果“The”在前或“Foundation”在后,列侬不会。由于名称不一定是唯一的,因此不会有任何完美的解决方案,但我相信您可以找到解决方法以使其在大多数情况下正常运行。

标签: php javascript jquery mysql


【解决方案1】:

我对 php 了解不多,但这里有一个使用 jQuery 1.4 的快速 JavaScript:

<div id="maindiv">
   John Lennon and Paul McCartney wrote some of the most popular songs in the history of rock music.
</div>


<script>
   $(document).ready(function(){
       myPage.linkify($("#maindiv"));
    })

var myPage = {
    map: {
            "John Lennon": 1,
            "Paul McCartney": 2,
            "Rock Music": 3
         },

    linkify: function(domEl){
        var htmlcopy = domEl.html();

        function buildLink(txt, loc){
            return '<a "href = /blah/'+loc+'>'+txt+'</a>';
        }

        for(i in myPage.map){
           var tmpStr = new RegExp(i,"gi");
           htmlcopy = htmlcopy.replace( tmpStr, buildLink(i, myPage.map[i]) );
       }

       domEl.html(htmlcopy);
    }
 }
</script>

myPage.map 将在服务器端从数据库构建。这也可以是对 Ajax 函数(将抓取地图)的回调,这样它就不会阻止页面的其余部分执行其操作。

【讨论】:

  • 感谢您花时间输入。我没有在网站上使用任何 javascript,但这看起来是一个完美的用途。我需要一段时间才能掌握 jquery,但我一直打算这样做有一段时间了。我认为我不希望 myPage.map 对网站的用户可见,因此我必须考虑通过 Ajax 来实现。
  • 如果您不希望您的用户能够看到地图,那么客户端方法将不是一个好的选择。任何通过网络传输的内容都可供查看者使用,包括 Ajax 响应。有一些服务器端 JS 实现,但在这种情况下,您最好在 php 中重新创建它。
  • 也许我得重新考虑是否需要让 myPage.map 不可见
  • 效果很好 - 谢谢。我对 jquery 很陌生,对 javascript 没有经验:我将如何通过 Ajax 函数获取 myPage.map?
  • 在此处查看文档:api.jquery.com/jQuery.getJSON 您将执行以下操作: $.getJSON('someurl/getMap.php', function(data) { myPage.map = data; });其中“someurl/getMap.php”是服务器上的一个函数,用于构建您需要的数据的 JSON 版本。
【解决方案2】:

最好的办法是以某种方式手动标记新闻帖子,以指示何时出现名称。这是防止遗漏名称或不正确解析名称的唯一方法,并避免从数据库中扫描每个新闻故事以查找每个可能的名称的巨大处理需求。

也许有类似 twittery 语法的东西:

@[John Lennon] and @[Paul McCartney] wrote some of the most popular songs in the history of rock music.

然后,当您想要显示新闻故事时,通过自定义排序的 markdown 样式函数运行它。它可以解析出这些标记,找到匹配的数据库记录,并生成链接。

在将新闻故事插入数据库之前将@[] 标记转换为链接会更有效,但这会更紧密地结合在一起 - 如果用户被删除或他的 ID 更改,则链接会损坏。存储 @[] 还可以更轻松地编辑故事。

更新

如果您必须自动检测名称并将其转换为链接,则可以通过非常严重的性能损失来实现,并且只会随着您添加更多名称而增加:

function linkify_names($news) {
  $people = query('select people_id, firstname, lastname from people');

  $from = $to = array();
  foreach ($people as $person) {
    $name = "$person->firstname $person->lastname";
    // TODO - escape regex chars in $name?

    // match [boundary]$name[boundary], case insensitive
    $from[] = "/(\b)($name)(\b)/i";

    // include boundaries in replacement; maintain case of found name
    $to[] = '$1<a href="/people/' . $person->people_id .'">$2</a>$3';
  }

  return preg_replace($from, $to, $news);
}

不同之处在于,您必须查找所有个名称,而不是只查找标有@[]标签的名称,并详尽地搜索每个名称。您不能依靠简单的正则表达式在新闻文档的正文中查找名称。

【讨论】:

  • 我实际上已经实现了这种解决方案(也许我应该在问题中提到它,但我想保持简单)。然而,我认为这是一个不太理想的解决方案,因为“新闻”项目可以由网站的许多用户中的任何一个添加。虽然我提供了以与您建议的方式类似的方式添加链接的功能 - 该网站的大多数用户都不会打扰使用该功能。所以我宁愿有一种“自动”的方式来做这件事。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多