免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: kofpet
打印 上一主题 下一主题

perl 大文件分析 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2012-11-02 17:26 |只看该作者
先切割成N个小文件,然后数量全部汇总在计算前1000,不然很可能会失真

论坛徽章:
0
12 [报告]
发表于 2012-11-02 20:41 |只看该作者
感谢各位的支持,在外出差中。。。

论坛徽章:
1
未羊
日期:2014-09-08 22:47:27
13 [报告]
发表于 2012-11-02 23:01 |只看该作者
回复 1# kofpet
  1. #如果能预计到日志文件中所有可能的url不超过100万个
  2. use strict;

  3. open my $log, "<", "your_log_file" or die $!;
  4. my ( %log );
  5. while ( <$log> ) {
  6.     chomp;
  7.     my $url = farse_url( $_ );
  8.     next unless $url;
  9.     $log{$url}++;
  10. }
  11. close $log;

  12. my $i;
  13. for my $key ( (sort { $log{$b}<=>$log{$a} } keys %log)[0..999] ) {
  14.     print "$key => $log{$key}\n";
  15. }

  16. sub farse_url {
  17.     my $line = shift;
  18.     .
  19.     .   # farse your url and return
  20.     .
  21.     return $url;
  22. }
复制代码

论坛徽章:
0
14 [报告]
发表于 2012-11-03 07:57 |只看该作者
这个是很典型的在一组数中求K个最大的数的算法。
1. 如果这些URL以后需要用,可以把日志里的URL全提出来放到一个文件里
2. 解析这些文件,可以按行读。也可以读取一个缓冲,如一次性读取几M,再按行读,需要处理断行的地方
3. 就是创建一个1000个元素的小顶堆,如遇到比堆顶大的元素,则替换堆顶元素,然则调整堆,保证其仍然是小顶堆

这种做法,与日志文件大小无关,需要的内存都是大小固定的。

论坛徽章:
1
未羊
日期:2014-09-08 22:47:27
15 [报告]
发表于 2012-11-03 08:58 |只看该作者
回复 14# jorneyR


    关键是要统计每个url的点击次数,这个怎么解决?

论坛徽章:
1
CU十二周年纪念徽章
日期:2013-10-24 15:41:34
16 [报告]
发表于 2012-11-03 10:07 |只看该作者
的确,处理这样的问题,想想可行的算法才是王道。

论坛徽章:
1
未羊
日期:2014-09-08 22:47:27
17 [报告]
发表于 2012-11-03 13:29 |只看该作者
本帖最后由 wxlfh 于 2012-11-03 13:52 编辑

回复 1# kofpet
  1. #如果600G文件中可能的url实在太多,以致根本不能放入内存中,那就来个不精确的排序
  2. #按行读取,超过500000个url,则把前2000名写入文件;然后再重复
  3. #最后在文件中统计,并输出前1000名
  4. use strict;

  5. open my $log, "<" , "your_log_file" or die $!;
  6. open my $fh , ">+", "LOG_HASH.txt"  or die $!;

  7. my ( %log,$max_key,$check,$i );
  8. $max_key = 50_0000;
  9. $check   =  1_0000;
  10. $limit   = 1999;

  11. while ( <$log> ) {
  12.     chomp;
  13.     my $url = farse_url( $_ );
  14.     next unless $url;
  15.     $i++;
  16.     $log{$url}++;
  17.     unless ( $i % $check ) {    # 每找到10000个url检查一次
  18.         my $keys = keys %log;
  19.         if ( $keys > $max_key ) { # 超过500000个url就把前2000名写入文件
  20.             write_file( [(sort { $log{$b}<=>$log{$a} } keys %log)[0..$limit]] );
  21.             %log = ( );
  22.         }
  23.         $i = 0;
  24.     }
  25. }
  26. write_file( [(sort { $log{$b}<=>$log{$a} } keys %log)[0..$limit]] );    # 最后不足500000个的,也把前2000名写入文件
  27. close $fh;
  28. %log = ( );

  29. open $log, "<", "LOG_HASH.txt" or die $!;
  30. while ( <$log> ) {
  31.     chomp;
  32.     $log{$1} += $2 if /^(\S+)\s=\s(\d+)/;
  33. }
  34. close $log;

  35. for ( (sort {$log{$b}<=>$log{$a}} keys %log)[0..999] ) {
  36.     print "$_ => $log{$_}\n";   # 打印前1000名url
  37. }

  38. sub farse_url {
  39.     my $line = shift;
  40.     .
  41.     .   # farse your url and return
  42.     .
  43.     return $url;
  44. }

  45. sub write_file {
  46.     my $keys = shift;
  47.     print $fh "$_ = $log{$_}\n" for @{$keys};
  48. }
复制代码

论坛徽章:
2
CU大牛徽章
日期:2013-04-17 11:46:28CU大牛徽章
日期:2013-04-17 11:46:39
18 [报告]
发表于 2012-11-03 14:13 |只看该作者
日志一般很少跨行的吧,这样就可以考虑逐行处理

论坛徽章:
0
19 [报告]
发表于 2012-11-04 06:32 |只看该作者
wxlfh 发表于 2012-11-03 08:58
回复 14# jorneyR

可以先把URL提出来放到一个文件里,使用文件排序,然后统计出每一个URL的点击次数,再求点击次数最多的1000个URL
^_^,最偷懒的办法,用数据库处理查询

论坛徽章:
0
20 [报告]
发表于 2012-11-05 10:28 |只看该作者
。。。。我忽然想到这是不是hadoop的典型案例?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP