我需要你的帮助:)
我有一个名为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]))
但我无法使其正常运作,你能帮助我吗?
答案 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]))