最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Python實(shí)現(xiàn)一個(gè)文件相似度檢測(cè)工具

 更新時(shí)間:2025年07月28日 09:15:00   作者:Yant224  
本文介紹基于Python的文件相似度檢測(cè)工具,支持余弦、Jaccard、編輯距離等算法,具備預(yù)處理、閾值判斷和健壯性處理,適用于文檔查重、代碼檢測(cè)及版本比較,需要的朋友可以參考下

基于文本內(nèi)容比較的相似度檢測(cè)工具

以下是一個(gè)完整的文件相似度檢測(cè)函數(shù)實(shí)現(xiàn),支持多種相似度算法和閾值判斷:

import difflib
from pathlib import Path
import re
from collections import Counter
import math
import string

def are_files_similar(
    file1: str | Path,
    file2: str | Path,
    similarity_threshold: float = 0.8,
    method: str = "cosine"
) -> bool:
    """
    比較兩個(gè)文件的相似度是否超過(guò)指定閾值
    
    參數(shù):
        file1: 第一個(gè)文件路徑
        file2: 第二個(gè)文件路徑
        similarity_threshold: 相似度閾值 (0-1)
        method: 相似度計(jì)算方法
            'cosine' - 余弦相似度 (默認(rèn))
            'jaccard' - Jaccard相似度
            'levenshtein' - 編輯距離相似度
            'sequence' - 序列匹配相似度
    
    返回:
        bool: 相似度是否超過(guò)閾值
    """
    # 讀取文件內(nèi)容
    content1 = _read_file(file1)
    content2 = _read_file(file2)
    
    # 空文件處理
    if not content1 and not content2:
        return True  # 兩個(gè)空文件視為相同
    
    # 選擇計(jì)算方法
    if method == "cosine":
        similarity = _cosine_similarity(content1, content2)
    elif method == "jaccard":
        similarity = _jaccard_similarity(content1, content2)
    elif method == "levenshtein":
        similarity = _levenshtein_similarity(content1, content2)
    elif method == "sequence":
        similarity = _sequence_similarity(content1, content2)
    else:
        raise ValueError(f"未知的相似度計(jì)算方法: {method}")
    
    return similarity >= similarity_threshold

def _read_file(file_path: str | Path) -> str:
    """讀取文件內(nèi)容并進(jìn)行預(yù)處理"""
    path = Path(file_path)
    if not path.exists():
        raise FileNotFoundError(f"文件不存在: {path}")
    
    # 讀取文件內(nèi)容
    try:
        with open(path, 'r', encoding='utf-8') as f:
            content = f.read()
    except UnicodeDecodeError:
        # 嘗試其他編碼
        with open(path, 'r', encoding='latin-1') as f:
            content = f.read()
    
    # 基礎(chǔ)預(yù)處理
    content = content.lower()
    content = re.sub(r'\s+', ' ', content)  # 合并連續(xù)空白
    return content.strip()

def _cosine_similarity(text1: str, text2: str) -> float:
    """計(jì)算余弦相似度"""
    # 創(chuàng)建詞頻向量
    vec1 = Counter(_tokenize(text1))
    vec2 = Counter(_tokenize(text2))
    
    # 獲取所有唯一詞
    words = set(vec1.keys()) | set(vec2.keys())
    
    # 創(chuàng)建向量
    vector1 = [vec1.get(word, 0) for word in words]
    vector2 = [vec2.get(word, 0) for word in words]
    
    # 計(jì)算點(diǎn)積
    dot_product = sum(v1 * v2 for v1, v2 in zip(vector1, vector2))
    
    # 計(jì)算模長(zhǎng)
    magnitude1 = math.sqrt(sum(v**2 for v in vector1))
    magnitude2 = math.sqrt(sum(v**2 for v in vector2))
    
    # 避免除以零
    if magnitude1 == 0 or magnitude2 == 0:
        return 0.0
    
    return dot_product / (magnitude1 * magnitude2)

def _jaccard_similarity(text1: str, text2: str) -> float:
    """計(jì)算Jaccard相似度"""
    set1 = set(_tokenize(text1))
    set2 = set(_tokenize(text2))
    
    intersection = len(set1 & set2)
    union = len(set1 | set2)
    
    if union == 0:
        return 1.0  # 兩個(gè)空集
    
    return intersection / union

def _levenshtein_similarity(text1: str, text2: str) -> float:
    """基于編輯距離的相似度"""
    # 計(jì)算編輯距離
    n, m = len(text1), len(text2)
    if n == 0 or m == 0:
        return 0.0
    
    # 創(chuàng)建距離矩陣
    d = [[0] * (m + 1) for _ in range(n + 1)]
    
    # 初始化邊界
    for i in range(n + 1):
        d[i][0] = i
    for j in range(m + 1):
        d[0][j] = j
    
    # 計(jì)算距離
    for i in range(1, n + 1):
        for j in range(1, m + 1):
            cost = 0 if text1[i - 1] == text2[j - 1] else 1
            d[i][j] = min(
                d[i - 1][j] + 1,      # 刪除
                d[i][j - 1] + 1,      # 插入
                d[i - 1][j - 1] + cost  # 替換
            )
    
    distance = d[n][m]
    max_len = max(n, m)
    return 1 - (distance / max_len)

def _sequence_similarity(text1: str, text2: str) -> float:
    """基于序列匹配的相似度"""
    matcher = difflib.SequenceMatcher(None, text1, text2)
    return matcher.ratio()

def _tokenize(text: str) -> list[str]:
    """文本分詞處理"""
    # 移除標(biāo)點(diǎn)
    text = text.translate(str.maketrans('', '', string.punctuation))
    # 分詞
    return text.split()

一、使用示例

1. 基本使用

# 比較兩個(gè)文件是否相似度超過(guò)80%
result = are_files_similar("file1.txt", "file2.txt", 0.8)
print(f"文件相似: {result}")

2. 使用不同算法

# 使用Jaccard相似度
result = are_files_similar("doc1.md", "doc2.md", method="jaccard")

# 使用編輯距離相似度
result = are_files_similar("code1.py", "code2.py", method="levenshtein")

3. 批量比較

def find_similar_files(directory, threshold=0.9):
    """查找目錄中相似的文件對(duì)"""
    from itertools import combinations
    files = list(Path(directory).glob("*"))
    
    similar_pairs = []
    for file1, file2 in combinations(files, 2):
        if are_files_similar(file1, file2, threshold):
            similar_pairs.append((file1.name, file2.name))
    
    return similar_pairs

二、功能特點(diǎn)

1. 多算法支持

算法適用場(chǎng)景特點(diǎn)
余弦相似度長(zhǎng)文檔、自然語(yǔ)言考慮詞頻,忽略詞序
Jaccard相似度短文本、關(guān)鍵詞匹配基于集合運(yùn)算
編輯距離相似度代碼、配置文件考慮字符級(jí)差異
序列匹配相似度通用文本Python內(nèi)置算法

2. 預(yù)處理流程

  1. 統(tǒng)一小寫(xiě)
  2. 合并連續(xù)空白
  3. 移除標(biāo)點(diǎn)符號(hào)(分詞時(shí))
  4. 標(biāo)準(zhǔn)化編碼處理

3. 健壯性設(shè)計(jì)

  • 自動(dòng)處理文件編碼問(wèn)題
  • 空文件特殊處理
  • 除零保護(hù)
  • 路徑對(duì)象兼容

三、性能優(yōu)化建議

1. 大文件處理

def _read_large_file(file_path: Path) -> str:
    """分塊讀取大文件"""
    content = []
    with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
        while True:
            chunk = f.read(65536)  # 64KB塊
            if not chunk:
                break
            content.append(chunk.lower())
    return ' '.join(content)

2. 內(nèi)存優(yōu)化版Jaccard

def _jaccard_similarity_large(text1: str, text2: str) -> float:
    """適用于大文件的Jaccard相似度"""
    # 使用最小哈希(minHash)近似計(jì)算
    from datasketch import MinHash
    
    # 創(chuàng)建MinHash對(duì)象
    m1 = MinHash(num_perm=128)
    m2 = MinHash(num_perm=128)
    
    # 添加詞元
    for word in set(_tokenize(text1)):
        m1.update(word.encode('utf-8'))
    
    for word in set(_tokenize(text2)):
        m2.update(word.encode('utf-8'))
    
    return m1.jaccard(m2)

3. 并行處理

from concurrent.futures import ThreadPoolExecutor

def batch_compare(file_pairs, threshold=0.8):
    """并行批量比較文件"""
    results = {}
    with ThreadPoolExecutor() as executor:
        futures = {
            (pair[0].name, pair[1].name): executor.submit(
                are_files_similar, pair[0], pair[1], threshold
            )
            for pair in file_pairs
        }
        
        for names, future in futures.items():
            results[names] = future.result()
    
    return results

四、應(yīng)用場(chǎng)景

1. 文檔查重

def check_plagiarism(submitted_file, source_files, threshold=0.7):
    """檢查文檔抄襲"""
    for source in source_files:
        if are_files_similar(submitted_file, source, threshold):
            print(f"檢測(cè)到與 {source} 相似")
            return True
    return False

2. 代碼相似度檢測(cè)

def detect_code_clones(repo_path):
    """檢測(cè)代碼庫(kù)中的相似代碼片段"""
    code_files = list(Path(repo_path).rglob("*.py"))
    clones = []
    
    for file1, file2 in combinations(code_files, 2):
        if are_files_similar(file1, file2, 0.85, method="levenshtein"):
            clones.append((file1, file2))
    
    return clones

3. 文件版本比較

def find_most_similar_version(target_file, versions):
    """在多個(gè)版本中查找最相似的文件"""
    similarities = []
    for version_file in versions:
        sim = are_files_similar(target_file, version_file, method="sequence")
        similarities.append((version_file, sim))
    
    # 按相似度排序
    return sorted(similarities, key=lambda x: x[1], reverse=True)[0]

五、測(cè)試用例

import unittest
import tempfile

class TestFileSimilarity(unittest.TestCase):
    def setUp(self):
        # 創(chuàng)建臨時(shí)文件
        self.file1 = tempfile.NamedTemporaryFile(delete=False, mode='w+')
        self.file2 = tempfile.NamedTemporaryFile(delete=False, mode='w+')
        self.file3 = tempfile.NamedTemporaryFile(delete=False, mode='w+')
        
        # 寫(xiě)入內(nèi)容
        self.file1.write("This is a test file for similarity comparison.")
        self.file2.write("This is a test file for similarity comparison.")
        self.file3.write("This is a completely different file content.")
        
        # 確保寫(xiě)入磁盤(pán)
        self.file1.flush()
        self.file2.flush()
        self.file3.flush()
    
    def test_identical_files(self):
        self.assertTrue(are_files_similar(self.file1.name, self.file2.name))
    
    def test_different_files(self):
        self.assertFalse(are_files_similar(self.file1.name, self.file3.name, 0.8))
    
    def test_empty_files(self):
        with tempfile.NamedTemporaryFile(mode='w+') as empty1, \
             tempfile.NamedTemporaryFile(mode='w+') as empty2:
            self.assertTrue(are_files_similar(empty1.name, empty2.name))
    
    def test_various_methods(self):
        # 相同文件應(yīng)所有方法都返回高相似度
        self.assertAlmostEqual(
            are_files_similar(self.file1.name, self.file2.name, 0.0, "cosine"), 
            1.0, delta=0.01
        )
        self.assertAlmostEqual(
            are_files_similar(self.file1.name, self.file2.name, 0.0, "jaccard"), 
            1.0, delta=0.01
        )
        self.assertAlmostEqual(
            are_files_similar(self.file1.name, self.file2.name, 0.0, "levenshtein"), 
            1.0, delta=0.01
        )
        self.assertAlmostEqual(
            are_files_similar(self.file1.name, self.file2.name, 0.0, "sequence"), 
            1.0, delta=0.01
        )
    
    def tearDown(self):
        # 清理臨時(shí)文件
        Path(self.file1.name).unlink()
        Path(self.file2.name).unlink()
        Path(self.file3.name).unlink()

if __name__ == "__main__":
    unittest.main()

總結(jié)

這個(gè)文件相似度檢測(cè)函數(shù)提供了:

  1. 多種算法選擇:余弦、Jaccard、編輯距離、序列匹配
  2. 閾值判斷:靈活設(shè)置相似度閾值
  3. 健壯性處理:編碼處理、空文件處理
  4. 易用接口:支持字符串和Path對(duì)象

使用示例:

# 基本使用
result = are_files_similar("file1.txt", "file2.txt", 0.75)

# 指定算法
result = are_files_similar("doc1.md", "doc2.md", method="jaccard")

通過(guò)這個(gè)函數(shù),您可以輕松實(shí)現(xiàn):

  • 文檔查重系統(tǒng)
  • 代碼克隆檢測(cè)
  • 文件版本比較
  • 內(nèi)容相似度分析

以上就是基于Python實(shí)現(xiàn)一個(gè)文件相似度檢測(cè)工具的詳細(xì)內(nèi)容,更多關(guān)于Python文件相似度檢測(cè)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python爬蟲(chóng)練習(xí)匯總

    Python爬蟲(chóng)練習(xí)匯總

    這篇文章主要給大家分享的是Python爬蟲(chóng)練習(xí)題,文章以爬取南陽(yáng)理工OJ為題目,根據(jù)頁(yè)面數(shù)據(jù)顯示可以查看到只有題號(hào)、難度、標(biāo)題、通過(guò)率、存有數(shù)據(jù),因此只需要對(duì)此四項(xiàng)數(shù)據(jù)進(jìn)行爬取,下面一起靜茹文章查看具體的操作過(guò)程吧</P><P>
    2021-12-12
  • Python中__new__與__init__方法的區(qū)別詳解

    Python中__new__與__init__方法的區(qū)別詳解

    這篇文章主要介紹了Python中__new__與__init__方法的區(qū)別,是Python學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-05-05
  • 使用Python在Windows和Linux上終止進(jìn)程的簡(jiǎn)易腳本分享

    使用Python在Windows和Linux上終止進(jìn)程的簡(jiǎn)易腳本分享

    終止系統(tǒng)中的進(jìn)程在日常運(yùn)維或開(kāi)發(fā)中是常見(jiàn)需求,但傳統(tǒng)方法常讓人頭疼,所以本文我將分享兩個(gè)Python腳本,分別用于Windows和Linux系統(tǒng),只需輸入進(jìn)程名即可終止目標(biāo)進(jìn)程,這些腳本簡(jiǎn)單易用,適合系統(tǒng)管理員和開(kāi)發(fā)人員,需要的朋友可以參考下
    2025-09-09
  • Python 中由 yield 實(shí)現(xiàn)異步操作

    Python 中由 yield 實(shí)現(xiàn)異步操作

    這篇文章主要介紹了Python 中由 yield 實(shí)現(xiàn)異步操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-05-05
  • python如何求取指定范圍內(nèi)的質(zhì)數(shù)

    python如何求取指定范圍內(nèi)的質(zhì)數(shù)

    這篇文章主要介紹了python如何求取指定范圍內(nèi)的質(zhì)數(shù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Selenium python時(shí)間控件輸入問(wèn)題解決方案

    Selenium python時(shí)間控件輸入問(wèn)題解決方案

    這篇文章主要介紹了Selenium python時(shí)間控件輸入問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • python 解決微分方程的操作(數(shù)值解法)

    python 解決微分方程的操作(數(shù)值解法)

    這篇文章主要介紹了python 解決微分方程的操作(數(shù)值解法),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-05-05
  • easyocr下載好幾次不成功的解決方案

    easyocr下載好幾次不成功的解決方案

    本文介紹了如何在控制臺(tái)中使用OCR軟件,并驗(yàn)證其是否成功,在PyCharm的Anaconda虛擬環(huán)境中遇到OMP:Error#15錯(cuò)誤時(shí),可能是由于多個(gè)庫(kù)沖突導(dǎo)致的,解決方法是在環(huán)境變量中添加特定的配置,然后重新運(yùn)行代碼即可驗(yàn)證問(wèn)題解決
    2025-11-11
  • 通過(guò)實(shí)例簡(jiǎn)單了解Python中yield的作用

    通過(guò)實(shí)例簡(jiǎn)單了解Python中yield的作用

    這篇文章主要介紹了通過(guò)實(shí)例簡(jiǎn)單了解Python中yield的作用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12
  • Centos環(huán)境部署django項(xiàng)目的全過(guò)程(永久復(fù)用)

    Centos環(huán)境部署django項(xiàng)目的全過(guò)程(永久復(fù)用)

    Django是一款針對(duì)Python環(huán)境的WEB開(kāi)發(fā)框架,能夠幫助我們構(gòu)架快捷,下面這篇文章主要給大家介紹了關(guān)于Centos環(huán)境部署django項(xiàng)目的相關(guān)資料,需要的朋友可以參考下
    2022-10-10

最新評(píng)論

宜宾市| 克东县| 丰都县| 宿松县| 湛江市| 大余县| 福贡县| 商河县| 新兴县| 聂拉木县| 呼图壁县| 普陀区| 邛崃市| 日土县| 隆德县| 尚志市| 东台市| 秦皇岛市| 乐业县| 广水市| 璧山县| 霍州市| 阿克苏市| 仁寿县| 开江县| 岑溪市| 利辛县| 五家渠市| 全南县| 红桥区| 阳山县| 濉溪县| 泰和县| 凌海市| 叶城县| 德阳市| 永顺县| 手游| 延长县| 永兴县| 丽水市|