IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> 使用分词增强Typecho的搜索功能 -> 正文阅读

[PHP知识库]使用分词增强Typecho的搜索功能

本博客是使用Typecho搭建的,侧边提供了搜索功能,然而Typecho内置的搜索功能仅仅只是基于字符串的全匹配查找,功能非常鸡肋,很多合理的查询都没法得到结果,比如“Transformer的文章”、“BERT的相关内容”都没有查询结果,因为文章中都不包含这些字符串

之前看到过苏剑林大佬的文章增强typecho的搜索功能,一开始觉得太麻烦,于是并没有考虑采用它的方法,转而在网上找一些增强Typecho搜索功能的插件。兜兜转转找了很多,发现效果都不是太好,最后还是决定考虑采用苏剑林大佬的方法

首先Typecho的搜索功能是在var/Widget/Archive.php中实现的,具体代码大概在1184~1191行(注意,我的Typecho版本是1.1)

if (!$hasPushed) {
    $searchQuery = '%' . str_replace(' ', '%', $keywords) . '%';
    /**搜索无法进入隐私项保护归档 */

    $select->where('table.contents.password IS NULL')
    ->where('table.contents.title LIKE ? OR table.contents.text LIKE ?', $searchQuery, $searchQuery)
    ->where('table.contents.type = ?', 'post');
}

从这个代码可以看出,搜索框内的字符会给到变量keywords,并且空格会被替换为通配符,关键词检索的范围包括title(标题)和text(正文)。那么很自然的一个想法是,首先通过分词工具对查询语句进行分词,然后对所有的文章进行一个排序,排序的规则是:文章的标题每包含一个词,加2分;文章的正文每包含一个词,加1分,最后算总分然后排序输出即可

为了实现上述目的,我们需要一个接口,输入句子,输出分词后的结果。说到分词,自然会想到python的很多分词库,但实际上php也有,不过我对php并不熟悉所以就不考虑了。分词很容易解决,但是如何将分词后的结果输出到网页上,或者说利用python写一个http接口,这其实是比较麻烦的,如果写的复杂就用flask,简单一点用bottle这个轻量级的库写http接口即可(下面的代码在python2环境下测试通过,python3应该也没问题。运行前先分别安装jiebabottlegunicorn三个库)

#! -*- coding:utf-8 -*-

import bottle
import jieba
import jieba.analyse
jieba.initialize()

def convert(s):
    ws = jieba.analyse.extract_tags(sentence=s, topK=5)
    search = []
    for i in ws:
        search.append('2*SIGN(INSTR(table.contents.title, "%s"))'%i)
        search.append('SIGN(INSTR(table.contents.text, "%s"))'%i)
    return '(%s)'%(' + '.join(search))

@bottle.route('/token', method='GET')
def token_home():
    text = bottle.request.GET.get('text')
    if not text:
        text = ''
    return convert(text)

if __name__ == '__main__':
    bottle.run(host='0.0.0.0', port=7778, server='gunicorn')

程序写好之后只需要在linux服务器中用python xxx.py运行即可,为了测试功能是否正常,可以通过访问http://域名:7778/token?text=进行测试

接下来是对Typecho源码的修改,具体来说是对Archive.php文件的修改,建议大家先保存一份副本。首先是将$keywords?=?$this->request->filter('url',?'search')->keywords;替换为$keywords?=?$this->request->keywords;,并将最前面提到的代码改为

if (!$hasPushed) {
    $url = 'http://127.0.0.1:7778/token?text=' . $keywords;
    $url = str_replace(' ', '%20', $url);
    $searchQuery = file_get_contents($url);

    /**当接口失效时使用简单全匹配 */
    if (!$searchQuery) {
        $searchQuery = 'SIGN(INSTR(table.contents.title, "' . $keywords . '"))';
        $searchQuery = $searchQuery . ' + SIGN(INSTR(table.contents.text, "' . $keywords . '"))';
    }

    /**搜索无法进入隐私项保护归档 */
    $select->where('table.contents.password IS NULL')
    ->where($searchQuery . ' > 0')
    ->where('table.contents.type = ?', 'post')
    ->order($searchQuery, Typecho_Db::SORT_DESC);
}

还有要修改的是:因为我们修改的部分order($searchQuery, Typecho_Db::SORT_DESC)按分数进行降序排序,然而这并不会直接生效,因为Typecho中默认全部按时间降序排列,因此我们还需要修改同一个文件的第1390~1391行,将原来的

$select->order('table.contents.created', Typecho_Db::SORT_DESC)
->page($this->_currentPage, $this->parameter->pageSize);

改为

if (strpos($select, 'INSTR') === false) {
    $select->page($this->_currentPage, $this->parameter->pageSize)
    ->order('table.contents.created', Typecho_Db::SORT_DESC);
} else {
    $select->page($this->_currentPage, $this->parameter->pageSize);
}

修改的这部分大概意思是先判断一下是不是搜索语句,如果是的话,就不按照时间排列;如果不是的话,就按照时间排列。直接去掉按时间排列是不行的,因为 这一句也包含了首页的输出,而首页的输出必须按照时间排序

PS:大家不要想着通过调用我的接口来偷懒,因为我并没有对外开放7778端口

Reference

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-09-04 17:17:00  更:2021-09-04 17:17:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 10:15:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码