2017-07-19 7 views
10

में शब्दकोशों की सूची में कुंजियों के मूल्यों को कुंजी के मान जोड़ें और इसे क्रमबद्ध करें मैं वास्तव में पाइथन के लिए नया हूं और मैं नीचे की समस्या से फंस गया हूं जिसे मुझे हल करने की आवश्यकता है। मैं नीचे के रूप में अपाचे लॉग से एक लॉग फ़ाइल है:पाइथन

[01/Aug/1995:00:54:59 -0400] "GET /images/opf-logo.gif HTTP/1.0" 200 32511 
[01/Aug/1995:00:55:04 -0400] "GET /images/ksclogosmall.gif HTTP/1.0" 200 3635 
[01/Aug/1995:00:55:06 -0400] "GET /images/ksclogosmall.gif HTTP/1.0" 403 298 
[01/Aug/1995:00:55:09 -0400] "GET /images/ksclogosmall.gif HTTP/1.0" 200 3635 
[01/Aug/1995:00:55:18 -0400] "GET /images/opf-logo.gif HTTP/1.0" 200 32511 
[01/Aug/1995:00:56:52 -0400] "GET /images/ksclogosmall.gif HTTP/1.0" 200 3635 

मैं 10 सबसे अनुरोध किया वस्तुओं और उनकी संचयी बाइट्स स्थानांतरित कर वापस जाने के लिए है। मुझे सफल (HTTP 2xx) प्रतिक्रियाओं के साथ केवल GET अनुरोधों को शामिल करने की आवश्यकता है।

तो ऊपर लॉग परिणाम होगा में:

/images/ksclogosmall.gif 10905 
/images/opf-logo.gif 65022 

अब तक मैं निम्नलिखित कोड है:

import re 
from collections import Counter, defaultdict 
from operator import itemgetter 
import itertools 
import sys 

log_file = "web.log" 
pattern = re.compile(
     r'\[(?P<date>[^\[\]:]+):(?P<time>\d+:\d+:\d+) (?P<timezone>[\-+]?\d\d\d\d)\] ' 
     + r'"(?P<method>\w+) (?P<path>[\S]+) (?P<protocol>[^"]+)" (?P<status>\d+) (?P<bytes_xfd>-|\d+)') 

dict_list = [] 

with open(log_file, "r") as f: 
    for line in f.readlines(): 
     if re.search("GET", line) and re.search(r'HTTP/[\d.]+"\s[2]\d{2}', line): 
      try: 
       log_line_data = pattern.match(line) 
       path = log_line_data["path"] 
       bytes_transferred = int(log_line_data["bytes_xfd"]) 
       dict_list.append({path: bytes_transferred}) 
      except: 
       print("Unexpected Error: ", sys.exc_info()[0]) 
       raise 
    f.close() 

print(dict_list) 

इस कोड शब्दकोश की निम्न सूची प्रिंट करता है।

/images/ksclogosmall.gif 10905 
/images/opf-logo.gif 65022 

इस परिणाम मूल रूप से कई बार विशेष कुंजी हुआ की संख्या द्वारा सॉर्ट समान चाबियाँ करने के लिए संगत मानों के अलावा है:

[{'/images/opf-logo.gif': 32511}, 
{'/images/ksclogosmall.gif': 3635}, 
{'/images/ksclogosmall.gif': 3635}, 
{'/images/opf-logo.gif': 32511}, 
{'/images/ksclogosmall.gif': 3635}] 

मैं यहाँ से जाने के लिए कैसे परिणाम प्राप्त करने के रूप में नहीं जानते एक क्रम क्रम में।

नोट: मैंने colllections.Counter का उपयोग करने का प्रयास किया, कोई फायदा नहीं हुआ, यहां मैं कुंजी की संख्या के अनुसार क्रमबद्ध करना चाहता हूं।

किसी भी मदद की सराहना की जाएगी।

उत्तर

8

आप एक collections.Counter उपयोग कर सकते हैं और update यह बाइट्स प्रत्येक वस्तु के लिए स्थानांतरित कर को जोड़ने के लिए:

from collections import Counter 
c = Counter() 
for d in dict_list: 
    c.update(d) 
occurrences=Counter([list(x.keys())[0] for x in dict_list]) 
sorted(c.items(), key=lambda x: occurrences[x[0]], reverse=True) 

आउटपुट:

[('/images/ksclogosmall.gif', 10905), ('/images/opf-logo.gif', 65022)] 
+0

मैं इस जोड़ने की कोशिश की है मौजूद हैं, लेकिन यह क नहीं है मुझे जरूरत है मुझे किसी विशेष कुंजी के समय की शब्दकोशों की सूची को क्रमबद्ध करने की आवश्यकता है और साथ ही साथ उनके मान भी जोड़े जाएंगे और अंतिम आउटपुट निम्नतम से निम्नतम होगा: /images/ksclogosmall.gif 10905 /छवियां/opf -logo.gif 65022 –

+0

ठीक है, मैंने अपना जवाब अपडेट कर दिया है। – Imran

+0

फिर भी वही, यह मानों द्वारा क्रमबद्ध है। मैं इसे किसी विशेष कुंजी के समय से क्रमबद्ध करना चाहता हूं, भले ही '/images/opf-logo.gif' कुंजी से संबंधित मान 65022 है, जैसा कि '/images/ksclogosmall.gif' के मान की तुलना में 10905 है , यह अभी भी शीर्ष पर होना चाहिए क्योंकि कुंजी '/images/ksclogosmall.gif' शब्दकोषों की सूची में 3 बार हुआ था, जो कि केवल दो बार हुआ था। किसी भी भ्रम के बारे में खेद है, मैं वास्तव में कुछ समय के लिए इस भाग पर वास्तव में अटक गया हूँ। –

0

आप पाश अपने dict कर सकते हैं और में मान संग्रहीत एक नया dict:

results = {} 
for d in dict_list: 
    for k, v in d.items(): 
     total = results.get(k, 0) # get previously stored value, 0 if none 
     results[k] = total + v 
0

यह सबसे सुरुचिपूर्ण समाधान नहीं हो सकता है, कैसे आर यह काम करेगा:

freq = {} 
with open('test.txt') as f: 
    lines = f.read().splitlines() 

    for line in lines: 
     if 'GET' in line and 'HTTP' in line and '200' in line: 
      path = line.split()[3] 
      occur = int(line.split()[-1]) 
      freq[path] = freq.get(path, 0) + occur 

frequency = {k: v for k, v in sorted(freq.items(), key=lambda x: x[1])} 

तो अपने प्रदान की लॉग टुकड़ा के लिए:

print(frequency) 
>>> {'/images/ksclogosmall.gif': 10905, '/images/opf-logo.gif': 65022} 
+0

मेरे पास वास्तव में यह आउटपुट है, मुझे जो चाहिए वह परिणाम है जो शब्दकोशों की सूची और उनके संचयी मूल्यों में एक कुंजी के साथ क्रमबद्ध होता है। /images/ksclogosmall.gif 10905 /images/opf-logo.gif 65022 –

+0

@ leo_21 आह क्षमा करें, मैंने गलत समझा, और मेरा जवाब अपडेट किया। – flevinkelming

+0

कोई चिंता नहीं। मुझे लगता है कि यह अभी भी मूल्यों द्वारा क्रमबद्ध उत्तर देता है, है ना? क्षमा करें मुझे यकीन नहीं है कि मुझे कोड सही मिला है या नहीं। मैं desc desc क्रम में एक कुंजी कितनी बार सॉर्ट कर सकता हूं और उनके संचयी मूल्य भी जोड़ सकता हूं? –

5

पहले, शब्दकोशों की एक सूची वास्तव में समझ में डेटा के इस प्रकार के लिए नहीं है। चूंकि प्रत्येक डिक्शनरी में केवल एक कुंजी-मूल्य वाली जोड़ी होगी, यदि आप अधिक पठनीयता चाहते हैं तो बस टुपल्स की एक सूची बनाएं (या namedtuples की एक सूची बनाएं)।

tuple_list.append((path, bytes_transferred)) 

अब, जो परिणाम आप चाहते हैं उसे प्राप्त करना अधिक सरल होगा। मैं व्यक्तिगत रूप से defaultdict का उपयोग करता हूं।

from collections import defaultdict 

tracker = defaultdict(list) 
for path, bytes_transferred in tuple_list: 
    tracker[path].append(bytes_transferred) 
# {'/images/ksclogosmall.gif': [3635, 3635, 3635], '/images/opf-logo.gif': [32511, 32511]} 

print([(p, sum(b)) for p, b in sorted(tracker.items(), key=lambda i: -len(i[1]))]) 
# [('/images/ksclogosmall.gif', 10905), ('/images/opf-logo.gif', 65022)] 
0

एक और विकल्प, दो पंक्तियों

.... 
path = log_line_data["path"] 
if [x for x in range(len(dict_list)) if path in dict_list[x].keys()]: 
    continue 

उत्पादन

[{'/images/opf-logo.gif': 32511}, {'/images/ksclogosmall.gif': 3635}] 
0

आप एक शब्दकोश में

[{'/images/opf-logo.gif': 32511}, 
{'/images/ksclogosmall.gif': 3635}, 
{'/images/ksclogosmall.gif': 3635}, 
{'/images/opf-logo.gif': 32511}, 
{'/images/ksclogosmall.gif': 3635}] 

संक्षिप्त करने के लिए करना चाहते हैं और एक ही साथ मूल्यों कुल हैं कुंजी:

  1. प्रत्येक शब्दकोश के माध्यम से एक नया, रिक्त शब्दकोश
  2. लूप बनाएं, देखें कि क्या कुंजी अपने नए शब्दकोश में मौजूद
  3. तो कुंजी (फ़ाइल पथ) मौजूद नहीं है, यह
  4. पर कॉपी यदि यह , मूल्य

`` `

total = {} 

for d in all: 
    for k, v in d.items(): 
      if k in total: 
        total[k] += v 
      else: 
        total[k] = v 

print(total) 
{'/images/opf-logo.gif': 65022, '/images/ksclogosmall.gif': 10905}