需要从列表中计算它们的项目

时间:2014-05-17 17:18:08

标签: python list count

我需要你的帮助:)

我有一个名为access_log.log的大日志文件,其中包含很多这样的行(没有空白行):

85.55.242.1 - - [22/Jan/2013:15:56:59 +0100] "GET /favicon.ico hxxp/1.1" 404 - "-" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.19 (KHTML, like Gecko) Ubuntu/10.04 Chromium/18.0.1025.168 Chrome/18.0.1025.168 Safari/535.19"

85.55.242.1 - - [22/Jan/2013:15:56:59 +0100] "GET /frutos.swf hxxp/1.1" 200 1454441 "hxxp://www.joquese.cat/frutos.html" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.19 (KHTML, like Gecko) Ubuntu/10.04 Chromium/18.0.1025.168 Chrome/18.0.1025.168 Safari/535.19"

85.55.242.1 - - [22/Jan/2013:15:56:59 +0100] "GET /plujasecs_mudo.flv hxxp/1.1" 200 1325949 "hxxp://www.joquese.cat/frutos.swf" "Mozilla/5.0 (X11; Linux i686) AppleWebKit/535.19 (KHTML, like Gecko) Ubuntu/10.04 Chromium/18.0.1025.168 Chrome/18.0.1025.168 Safari/535.19"

88.2.214.254 - - [22/Jan/2013:16:25:23 +0100] "GET / hxxp/1.1" 200 2722 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/536.26.17 (KHTML, like Gecko) Version/6.0.2 Safari/536.26.17"

我"战斗"使用python从每行中提取引用者,并列出50个最常见的副本数。我知道用#34; awk"会很容易但我想学习如何用python做到这一点。我所做的是将空格标记为字段分隔符,并在字段编号十和十一之间取字符串。

arxiu_de_log = open("access_log.log","r")
linies = arxiu_de_log.readlines()
arxiu_de_log.close() 

clean_log=[]
for line in linies:
    try:
        separador_de_linea=line.split(' ')
        camp_de_referer = separador_de_linea[10:11]
        clean_log.append(camp_de_referer)

    except:
        pass

print clean_log

当我运行程序时,我得到的是:

[['"-"'], ['"hxxp://www.joquese.cat/frutos.html"'], ['"hxxp://www.joquese.cat/frutos.swf"'], ['"-"'], ['"hxxp://www.joquese.cat/"']

但我想要类似的东西:

2   "-"

1   "hxxp://www.joquese.cat/frutos.swf"

1   "hxxp://www.joquese.cat/frutos.swf"

1   "hxxp://www.joquese.cat/"

....

我试图用类似于:

的程序对计数器进行编程
import collections
...
counter = collections.Counter(clean_log)

for count in counter.most_common(50):
    print(str(count[1])+"\t"+ str(count[0]))

但我无法使其正常运作,你能帮助我吗?

2 个答案:

答案 0 :(得分:1)

看起来你已经非常接近你想要的东西了。要记住的一件事是separador_de_linea[10:11]是一个列表,而separador_de_linea[10]是一个字符串。我想你想要字符串:

import collections
count = collections.Counter()
with open("access_log.log","r") as arxiu_de_log:
    for line in arxiu_de_log:
        line = line.strip()
        if line:
            separador_de_linea = line.split()
            camp_de_referer = separador_de_linea[10]
            count[camp_de_referer] += 1

for referer, cnt in count.most_common(50):
    print('{} {}'.format(cnt, referer))

产量

2 "-"
1 "hxxp://www.joquese.cat/frutos.swf"
1 "hxxp://www.joquese.cat/frutos.html"

这样可以避免创建clean_log列表来节省内存。


提示:

  • 而不是

    arxiu_de_log = open("access_log.log","r")
    

    使用a with-statement

    with open("access_log.log","r") as arxiu_de_log:
    

    当Python的执行流程离开时,文件将被关闭 与语句。因此,您不必(记得)调用

    arxiu_de_log.close()
    

    表达自己。

  • 尽可能避免调用readlines(),因为这会加载 将整个文件存入内存,并创建所有行的Python列表。 除非你需要在内存中保存的所有行,否则不要这样做 同时。在许多情况下,您所需要的只是一次一行。所以 而不是

    linies = arxiu_de_log.readlines()
    

    使用

    for line in arxiu_de_log:
    
  • except语句中使用裸try...except是一个坏习惯。 它会比你期望的更多,比如KeyboardInterrupt和。{ SystemExit个例外。最佳做法是仅捕获错误 你想要处理。在这种情况下

    try:
        ...
    except IndexError:
        pass
    

    会更好。

答案 1 :(得分:0)

您不能使用Counter列表,只能使用可清除类型。你为什么还要把推荐人列入名单?

import collections

with open("access_log.log","r") as arxiu_de_log:
    clean_log = [
        (line.split(' ')+[None]*10)[10]
        for line in arxiu_de_log]

counter = collections.Counter(clean_log)

for count in counter.most_common(50):
    print(str(count[1])+"\t"+ str(count[0]))