想象一下,我有一个充满行的日志文件:
" a,b,c",而这些变量可以有任何价值,但价值的重新出现确实会发生,这就是这个分析的内容。
映射所有'' 网址,其中'' 等于特定域,例如" stackoverflow.com"和c等于" stackoverflow.com/test/user /"我写了一个正则表达式来完成这个。
计算(减少)所有已计算的 c (网址),以便我有一个列表,其中包含每个网址的总计数。这很好。
第三步
(尚未实施和此qeustion的主题)
查找步骤2中每个计算网址的所有 b (浏览器名称)。回馈关系列表,例如字典ADT或JSON,如下所示:
[
{
"url":Stackoverflow.com/login,
"count": 200.654,
"browsers":[
Firefox 33,
IE 7,
Opera
]
},
{..},
{..}
],
我正在考虑在我的代码中引入一个合并器(见下文)或链式东西。但真正的问题是如何优化我的工作流程,以便我只需要遍历所有日志行一次?
FULL_URL_WHERE_DOMAIN_EQUALS = mySuperCoolRegex
class MRReferralAnalysis(MRJob):
def mapper(self, _, line):
for group in FULL_URL_WHERE_DOMAIN_EQUALS.findall(line):
yield (group, 1)
def reducer(self, itemOfInterest, counts):
yield (sum(counts), itemOfInterest)
def steps(self):
return [
MRStep( mapper=self.mapper,
reducer=self.reducer)
]
if __name__ == '__main__':
MRReferralAnalysis.run()
这就是我想要的伪代码:
LOGS_1 -> MAPREDUCE OVER SOME_CRITERIA -> LIST_1
FOR EVERY ITEM IN LIST_1:
LOGS_1 -> MAPREDUCE OVER ITEM_CRITERIA -> LIST_2
答案 0 :(得分:1)
这是非MRJob,非mapreduce 解决方案。它运行一次日志文件。它与您的输出规范略有不同,browsers
是(浏览器,计数)元组的列表,它生成无序的字典。 collections.OrderedDict
可以替代。
假设文件看起来像这样
domain,browser,url
wonderful.edu,IE,wonderful.edu/pix
odd.org,Firefox,odd.org/login
wonderful.edu,Opera,wonderful.edu/pix
阅读文件并按域,网址,浏览器排序,以便与itertools.groupby
import collections, itertools, operator
with open('fake.log') as f:
lines = [tuple(line.strip().split(',')) for line in f]
lines.sort(key = operator.itemgetter(0,2,1))
一些有用的callables
domain = operator.itemgetter(0)
browser = operator.itemgetter(1)
url = operator.itemgetter(2)
使用collections.Counter
计算每个唯一网址的浏览器数。网址数是所有浏览器计数的总和。
results = list()
FULL_URL_WHERE_DOMAIN_EQUALS = re.compile('.*\.(edu|org|com)')
for d, group in itertools.groupby(lines, domain):
# this outer loop only needed if filtering by domain
if not FULL_URL_WHERE_DOMAIN_EQUALS.match(d):
print d
continue
for u, group2 in itertools.groupby(group, url):
browsers = itertools.imap(browser, group2)
browser_count = collections.Counter(browsers)
results.append({'url' : u,
'count' : sum(browser_count.viewvalues()),
'browsers' : browser_count.items()}
)
可生产
[{'browsers': [('Chrome', 2), ('IE', 4), ('Opera', 7), ('Firefox', 6)],
'count': 19,
'url': 'odd.org/foo'},
{...},
{...}]