R语言预处理Twitter推文时如何剔除高度相似重复内容
R环境下剔除Twitter爬取数据中高相似度机器人推文方案
针对仅存在细微差异、多为机器人生成的重复推文问题,可按文本清洗、相似度匹配、聚类去重三步实现,适配R语言环境,处理十万级以内推文数据效率足够。
第一步:基础文本清洗,优先过滤无意义随机后缀
你给出的示例中,两条推文核心内容完全一致,仅末尾存在无意义随机字符串,先通过规则清洗可大幅降低后续相似度计算的误差:
- 统一将文本转为小写,移除所有URL链接、@提及用户、话题符号、标点、多余空白字符
- 用正则匹配并移除推文末尾8位以上连续无意义字母数字组合,也就是这类机器人推文常带的随机追踪后缀
对应可直接复用的R代码如下:
library(stringr) library(dplyr) clean_tweet <- function(raw_text) { text <- tolower(raw_text) # 移除链接、@用户、话题标记 text <- str_replace_all(text, "https?://\\S+|@\\w+|#", "") # 移除所有标点 text <- str_replace_all(text, "[[:punct:]]", "") # 合并多余空格 text <- str_replace_all(text, "\\s+", " ") %>% str_trim() # 移除末尾8位以上连续字母数字随机串 text <- str_replace_all(text, "[a-z0-9]{8,}$", "") return(text) } # 给推文数据框增加清洗后文本列,假设原始推文存在text列 df$cleaned_text <- sapply(df$text, clean_tweet)
按上述规则处理你给出的两条示例,末尾随机串会被完全清除,清洗后文本完全一致,可直接被识别为重复内容。
第二步:计算文本相似度,定位高相似推文对
针对短文本的高相似内容识别,优先用局部敏感哈希搭配Jaccard相似度的方案,计算速度快,对仅差几个字符的变体内容识别精度高:
- 基于3字符粒度的n-gram生成文本特征,适配推文的短文本特性
- 相似度阈值设为0.9,即两条文本重合度超过90%就判定为同内容的机器人生成变体
对应R实现代码:
library(textreuse) # 配置局部敏感哈希参数 minhash_func <- minhash_generator(n = 200, seed = 123) # 构建文本语料库 tweet_corpus <- TextReuseCorpus( text = df$cleaned_text, tokenizer = tokenize_ngrams, n = 3, minhash_func = minhash_func, keep_tokens = FALSE, progress = FALSE ) # 分桶找候选相似对,再计算精确Jaccard相似度 lsh_buckets <- lsh(tweet_corpus, bands = 50, seed = 123) sim_candidates <- lsh_candidates(lsh_buckets) sim_score <- lsh_compare(sim_candidates, tweet_corpus, jaccard_similarity) # 筛选相似度大于0.9的高相似对 high_sim_pairs <- sim_score[sim_score$score > 0.9, ]
如果你的数据量在1万条以内,也可以直接用stringdist包计算字符串编辑距离,编辑距离小于3的文本基本都是这类细微差异的重复内容,只是计算速度比上述局部敏感哈希方案慢,不适合大数据量。
第三步:聚类归并相似簇,完成去重
拿到高相似推文对之后,通过图连通分量把所有互相关联的相似推文归为同一个簇(比如A和B相似、B和C相似,那A/B/C就归为同一簇),每个簇仅保留1条代表内容即可:
library(igraph) # 基于相似对构建无向图 sim_graph <- graph_from_data_frame(high_sim_pairs[, c("a", "b")], directed = FALSE) # 识别连通分量,每个分量对应一个相似推文簇 sim_clusters <- components(sim_graph) # 给原始数据匹配簇ID df$sim_cluster <- NA df$sim_cluster[as.numeric(names(sim_clusters$membership))] <- sim_clusters$membership # 去重:每个相似簇保留1条,无相似匹配的内容全部保留 df_dedup <- df %>% group_by(sim_cluster) %>% slice(1) %>% # 如果有发布时间字段,也可以按发布时间排序后保留最早的一条 ungroup() %>% select(-sim_cluster)
实操时可以根据数据情况调整阈值:如果还有漏检的相似内容,就把相似度阈值降到0.85;如果出现误删正常内容的情况,就把阈值提升到0.95。你遇到的这类带随机后缀的机器人推文,清洗后相似度基本接近100%,几乎不会出现误判。
内容的提问来源于stack exchange,提问作者ignacywawa
相关产品推荐
相关产品推荐

