python 实现余弦相似度过滤豆瓣租房小组中介贴

915 阅读3分钟
原文链接: zhuanlan.zhihu.com

前几天做了个[微信找房机器人](https://zhuanlan.zhihu.com/p/23798922), 爬取豆瓣租房小组的时候发现很多伪装的中介帖,如下这种格式:

可月付 无中介 方庄地铁附近 芳城园一区单间出租

可月付 无中介 方庄地铁附近 芳城园一区主卧次卧出租

方庄地铁附近 芳城园一区次卧出租

豆瓣对于小组的帖子有个简单的过滤,如果标题完全一样,就会直接删除,所以中介们一般都会在标题改几个字,内容也会调整下顺序。其实对于这种问题,有简单的方案实现,比如下文介绍的余弦相似度。

关于余弦相似度的原理其实很简单,参考这篇文章[TF-IDF与余弦相似性的应用(二):找出相似文章](http://www.ruanyifeng.com/blog/2013/03/cosine_similarity.html)

python 实现如下:

(一) 对文本分词

def cut_word(content):

    tags = jieba.analyse.extract_tags(content, withWeight=True, topK=20)

    return tags

这里用了 jieba , 分词什么的它太有用了

(二) 返回两个文本词频的多维向量

def merge_tag(tag1=None, tag2=None):
    v1 = []
    v2 = []
    tag_dict1 = {i[0]: i[1] for i in tag1}
    tag_dict2 = {i[0]: i[1] for i in tag2}
    merged_tag = set(tag_dict1.keys()+tag_dict2.keys())
    for i in merged_tag:
        if i in tag_dict1:
            v1.append(tag_dict1[i])
        else:
            v1.append(0)
        if i in tag_dict2:
            v2.append(tag_dict2[i])
        else:
            v2.append(0)
    return v1, v2

(三) 计算余弦相似度

def dot_product(v1, v2):
    return sum(a * b for a, b in zip(v1, v2))

def magnitude(vector):
    return sqrt(dot_product(vector, vector))

def similarity(v1, v2):
    '''计算余弦相似度

    '''
    return dot_product(v1, v2) / (magnitude(v1) * magnitude(v2) + .00000000001)

(四) 结果

我们取一些样本做例子,内容为标题+详情

    # https://www.douban.com/group/topic/93410497/
    content1 = u"""

                可月付 无中介 方庄地铁附近 芳城园一区单间出租

                我的房子在方庄地铁附近的芳城园一区,正规小区楼房,

                三家合住,现出租一间主卧和一间带小阳台次卧,室内家电齐全,

                冰箱,洗衣机等都有,可洗澡上网,做饭都可以,小区交通便利,四通八达,

                希望入住的是附近正常上班的朋友

                """
    # https://www.douban.com/group/topic/93410328/
    content2 = u"""

                可月付 无中介 方庄地铁附近 芳城园一区主卧次卧出租

                我的房子在方庄地铁附近的芳城园一区,正规小区楼房,

                三家合住,现出租一间主卧和一间带小阳台次卧,室内家电齐全,

                冰箱,洗衣机等都有,可洗澡上网,做饭都可以,小区交通便利,四通八达,

                希望入住的是附近正常上班的朋友

                """
    # https://www.douban.com/group/topic/93410308/
    content3 = u"""方庄地铁附近 芳城园一区次卧出租

                    我的房子在方庄地铁附近的芳城园一区,正规小区楼房,

                    三家合住,现出租一间主卧和一间带小阳台次卧,室内家电齐全,

                    冰箱,洗衣机等都有,可洗澡上网,做饭都可以,小区交通便利,四通八达,

                    希望入住的是附近正常上班的朋友

                    """
    # https://www.douban.com/group/topic/93381171/
    content4 = u"""二环玉蜓桥旁下月27号后可入住二居

                方庄方古园一区5号楼下月27日到期出租,

                我是房主无中介费 ,新一年租6000元每月押一付三,主次卧可分开住。

                距地铁5号线蒲黄榆站5分钟路程。房屋60平正向,另有看守固定车位。

测试结果如下, 越接近 1 则两者文章越相似

content1 和 content2 相似度为: 0.968802386285

content1 和 content3 相似度为: 0.926323584519

content2 和 content3 相似度为: 0.921885685549

content2 和 content4 相似度为: 0.174889264654

说明 content1 content2 content3 很可能是中介批量发的帖子

这次只是简单的研究下,如果要起到更好效果,就得有这些关键词的语料,然后加权重。

代码见 [cosine_similarity.py](https://gist.github.com/facert/097af928b50ef9946513c7a5b42ec5c2)