首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >沪漂小窝添加相同内容去重功能

沪漂小窝添加相同内容去重功能

作者头像
马拉松程序员
发布2022-04-26 18:58:05
发布2022-04-26 18:58:05
7060
举报

前言:

五一假期的时候,对沪漂小窝进行了一下升级,把文本分类器的实现改成了自主实现,看着很深奥,其实很简单,我在群里分享后,有个小伙伴说,有一些信息是重复的,当时我说这里仅仅实现了按照id去重,并没有按照语义去重。

优化思路:

当时我是想着如果全数据库搜索,挨个排查,会很费劲。其实我忽略了一点,想这种标题相似度很高的帖子其实都是同一个创建者(同一个id)发布的,换句话说只需要将最近一个月内当前创建id的在数据库的帖子查询出来,遍历一遍,如果其中一个跟待入库的信息相似度很高,那么就可以认为是重度的帖子,对于系统筛选来说是无意义的内容,则不入库。

那么这样把内容理出来,实现就比较简单了。在可操作性上和时效性上,并没有很大的阻碍。

具体实现:

那么如何进行相似度区分呢,这个很简单,在之前使用分类算法的时候,计算的是段落的TF-IDF值,那么两个TF-IDF的向量很接近,那么就可以认为这两句话是表达同一个内容。关键点就在于这个阈值怎么界定。

先用个例子来演示一下,比较两个句子之前的相似性。

代码语言:javascript
复制
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
from scipy.linalg import norm

def tfidf_similarity(s1, s2):
    # 文字拆分
    s1, s2 = ' '.join(list(s1)), ' '.join(list(s2))
    # 转化为TF矩阵
    cv = TfidfVectorizer(tokenizer=lambda s: s.split())
    corpus = [s1, s2]
    vectors = cv.fit_transform(corpus).toarray()
    # 计算TF系数
    return np.dot(vectors[0], vectors[1]) / (norm(vectors[0]) * norm(vectors[1]))

if __name__ == '__main__':
    new = '全上海地铁沿线 整租公寓 小区整租合租 押一付一无中介费。拎包入住 '
    s1 = '中介勿扰,个人实帖直租12号线虹漕路地铁口,华悦家园独立一室户3400,可押1付1,紧邻漕河泾田林上师大。'
    s2 = '13号线金运路地铁口,大宅风范城,精装朝南一室户燃气厨房,家电全配,拎包入住,押一付一'
    s3 = '全上海地铁沿线 整租公寓 精装小区房,整租一室户。押一付一 无中介费'

    print(tfidf_similarity(s1, new))
    print(tfidf_similarity(s2, new))
    print(tfidf_similarity(s3, new))
    
代码运行结果:
0.15741852956377606
0.18237168346404925
0.7414888327522697

上文的例子表示,假设现在数据库中已经保存了A发布(时间选择最近一个月)的3条帖子,分别是s1,s2,s3。现在有一条A新发布的帖子的内容(标题)为new。现在将new分别与3条信息比对,发现中new和s3的TF系数比较高。比较两个文本,可以发现,这两个内容表达的意思基本是一样的。

那么由此断定new这条数据是无效数据或者说用户重复发布的信息,不应该是进入到信息筛选表中,所以直接pass。

以前玩豆瓣(发沪漂小窝的广告)的时候,可能有这么一个限制是短时间内不能发布同样的信息,所以就会把相同内容的帖子,修改一下名字,加一些空格、特殊字符(比如~,!!等等),已达到多次发布的效果。这样增加可能被别人看到的概率。

代码升级:

代码语言:javascript
复制
#更新 MyscrapyPipeline 方法
class MyscrapyPipeline:
    def process_item(self, item, spider):
        result = [item["title"], item["createDate"], item["text"], item["crawDate"], item["url"], item["creator"]]
        haveOne = [item["creator"]]
        image_urls = item["image_urls"]
        # 查询同一个创建者最近一个月发布的帖子
        querySql = "select title from house_info where creator=(%s)  and crawDate >= DATE_SUB(NOW(),INTERVAL 30 day)"
        houses = dbUtil.get_all(querySql, haveOne)
        # 如果存在相同的帖子则不保存
        if rentClassify.check(houses, item["title"]):
            saveSql = "insert into house_info (title, createDate, text,crawDate,url,creator) values (%s,%s,%s,%s,%s,%s)"
            h_id = dbUtil.save(saveSql, result)
            # 分析租房信息的分类
            info = rentClassify.analysis(item["url"], item["creator"], item["title"] + item["text"])
            # 添加租房信息的id
            info.append(h_id)
            infoSaveSql = "insert into rent_info (url, station, `identity`,price,pay,only_girl,rent_type,`count`,create_date,h_id) values (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
            # 保存信息分类
            r_id = dbUtil.save(infoSaveSql, info)
            # 图片链接保存
            if len(image_urls) > 0:
                imageSql = "INSERT INTO image(r_id,url) VALUES (%s,%s)"
                for image_url in image_urls:
                    i = [r_id, image_url]
                    dbUtil.save(imageSql, i)
        return item

全部完整代码已经push到我的github中,感兴趣的可以pull或者clone

地址:https://github.com/mlscoder/hupiao

PS:

小程序移动端和服务端也做了相应的改动,主要是表字段和结构的更新,最新版本的代码更新在github上。原来gitee的内容是老版本的内容,与现在的版本的不兼容。有需要的可以去这里获取。

我是马拉松程序员,可不止于代码!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 马拉松程序员 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档