Skip to main content
 首页 » 编程设计

python之如何使用 MapReduce 概念找出 HDFS 目录中的重复文档

2025年05月04日27shangdawei

我正在使用 Anaconda、spark 1.3 和 hadoop。我在 hdfs 的特定目录中存储了 xml 文档列表。

我必须使用 python 脚本加载该 xml 文档,以使用 spark 找出重复的文档。

例子:

conf = SparkConf().setAppName("Sample").setMaster("local[*]") 
sc = SparkContext(conf=conf) 
dir = sc.textFile("hdfs://XXXXXXX") 
configfiles = [os.path.join(dirpath, f) for dirpath, dirnames, files in os.walk(dir)for f in files if f.endswith('.xml')] 

在这方面我遇到了一些错误:

TypeError: coercing to Unicode: need string or buffer, RDD found 

hdfs://xxxxxx MapPartitionsRDD[1] at textFile at NativeMethodAccessorImpl.java:-2

我使用布隆过滤器通过生成哈希值来查找重复项。这在这里不是问题。

通过访问本地存储的文件但不能处理 hdfs 存储的文件。

谁能帮我解决这个问题?

提前致谢

请您参考如下方法:

该错误意味着您正在尝试将非字符串类型(Spark RDD)附加到某处的字符串。如果你阅读 the docs ,您会看到 sc.textFile 正在返回一个 RDD,因此您可能不能将其传递给 os.walk,因为它不是文件路径。您可以尝试调用collect在 RDD 上获取要迭代的列表以传递给 os.walk:

from collections import DefaultDict 
#from http://stackoverflow.com/a/3431835/301807 
import hashlib 
def hashfile(afile, hasher, blocksize=65536): 
    buf = afile.read(blocksize) 
    while len(buf) > 0: 
        hasher.update(buf) 
        buf = afile.read(blocksize) 
    return hasher.digest() 
 
dirs = sc.textFile("hdfs://XXXXXXX").collect() #returns a list, not an RDD 
configfiles = DefaultDict(list) 
for dir in dirs: #for each directory in the list from Spark 
    for dirpath, dirnames, files in os.walk(dir): #call os.walk with the directory 
        for f in files if f.endswith('.xml'): #iterate over the files in the directory 
            path = os.path.join(dirpath, f) #get the file's full path 
            digest = hashfile(open(path, 'rb'), hashlib.md5()) #hash the contents 
            configfiles[digest].append(path) 

您最终会得到一个将 MD5 总和映射到文件路径的字典。任何具有多个文件路径的 MD5 总和表示这些文件是重复的。这应该只打印重复项:

for md5, paths in configfiles.items() if len(paths) > 1: 
    print("The following files are duplicates of each other: '" + "', '".join(paths) + "'")