第一次用python写简单的mapreduce程序。python中有一个很好用的包叫mrjob.job,写代码时可以只需要用到其中的MRJob类。
除了可以在linux下运行,也可以在windows中直接运行。无需搭建hadoop集群,如果在windows中使用Pycharm,只需要在Configuration中的Parameter添加要读取的文件即可。
具体代码
(1)词频统计
from mrjob.job import MRJob
class MRWordFrequencyCount(MRJob):
def mapper(self, key, value):
#获取行中的单词数组
data = value.split()
for ele in data:
#对每个读取到的单词,返回key-pair(ele, 1)
yield ele, 1
def reducer(self, key, values):
#累加单词出现次数
yield key, sum(values)
if __name__ == '__main__':
MRWordFrequencyCount.run()
上述代码实现了统计文本中每个单词出现的频次。
在写mapreduce程序时,需要创建一个类继承MRJob,然后分别定义mapper方法和reducer方法。
(2)url统计
给一段log记录,其中有日期信息和url信息,返回2023年中每个url出现的次数。
假设log文件如下:
2022-01-02 www.google.com
2023-02-08 www.google.com
2023-02-15 www.baidu.com
2023-04-04 www.baidu.com
2023-07-02 www.google.com
rom mrjob.job import MRJob
class MRmyjob(MRJob):
def mapper(self, key, value):
data = value.split()
date = data[0].strip()
url = data[1].strip()
year = date[0:4]
#过滤年份数据
if year == '2023':
yield url, 1
def reducer(self, key, values):
yield key, sum(values)
if __name__ == '__main__':
MRmyjob.run()
运行结果为:
(3)统计每个月里出现最多次的url
from mrjob.job import MRJob
from mrjob.step import MRStep
class Mrmyjob(MRJob):
def mapper1(self,key,values):
data = values.split()
date = data[0].strip()
url = data[1].strip()
year = date[0:4]
month = date[5:7]
if year=='2023':
#以月份和url作为key
yield (month, url), 1
def reducer1(self, key, values):
#以月份作为key,但是注意这里的value为map中key对应value的求和,也就是某月中某个url的出
#现次数
#key[1]代表url,作为标记放到value中
yield (key[0], (sum(values),key[1]))
def reducer2(self,key,listOfValues):
#此时的key为月份,对于上述的(sum(values),key[1])),max(listOfValues)会根据第一个
#值的大小进行比较,也就是根据sum(values)即单个url在该月出现次数进行比较
yield key,max(listOfValues)
#定义两次mapreduce的执行顺序
def steps(self):
return [MRStep(mapper=self.mapper1,
reducer=self.reducer1),
MRStep(reducer=self.reducer2)]
if __name__ == '__main__':
Mrmyjob.run()
这段代码的整体逻辑是,第一次使用mapreduce统计每个月里每个url出现的次数,之后将输出的结果放到下一个mapreduce程序,返回每个月中出现次数最多的url。由于第二次mapreduce程序中只需要在第一次reduce后的结果中找出最大值,不需要mapper作任何处理,所以只需要一个reducer即可。
同样使用(2)的文件,
结果如下: