Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Andrey Yantsen
    @andrey-yantsen
    И тупо...
    def parse_line(line):
        ip, _, _, dt, tz, method, path, _, responce_code, size = line.split(' ')
        return ip, (dt + tz).replace('[', '').replace(']', ''), method.replace('"', ''), path, responce_code, size.strip()
    А вот и нет скобочек
    Alexey Lavrenuke
    @direvius
    @andrey-yantsen квдратные скобки в дате =)
    Alex Khaerov
    @hayorov
    pip install apache-log-parser
    Dima Beloborodov
    @beloborodov
    def parse_line(line):
        return re.search('(.*) - - \[(.*)\] "(.*) (\/.*) HTTP/1.0" (.*) (.*)', line).groups()
    Alexey Lavrenuke
    @direvius

    Задачка 2: починка парсера

    Задание Починить парсер хотя бы для тех ответов, которые обработал сервер

    • нераспаршенными должны остаться только те ответы, на которые сервер выдал код 400 (bad request)
    • предположим, что сервер читает url до первого пробельного символа, все остальное выкидывает

    Заготовка кода

    Можно либо поменять регулярное выражение, либо использовать свою функцию.

    import re
    
    def test_parser_on_file(parser):
        with open("./access_log_Jul95", encoding="ascii", errors="replace") as datafile:
            for line in datafile:
                try:
                    parser(line)
                except Exception as e:
                    # если парсер не сработает, напечатаем строку,
                    # на которой он сломался, и выйдем
                    print(line)
                    raise e
    
    regex = re.compile('([\w\-\.@]+) - - \[(.*?)\] "([A-Z]+) (\S+)(?:\s+(\S+))?" (\d+) (-|\d+)')
    def parse_line_re(line):
        try:
            return regex.match(line).groups()
        except AttributeError:
            print(line)
            return None
    
    test_parser_on_file(parse_line_re)
    Nikita Vdovushkin
    @briskly
    #briskly
    import re
    def parse_line(line):
        res = re.match(r"(.*)- - (\[.*\]) \"(\w+) (.+)( (.+))?\" (\d+) (\d+|-)", line)
        if res is None:
            print line
            return
        return res.groups()
    
    def parser_log(fn):
        for line in open(fn):
            res = parse_line(line)
            if res:
                pass
    
    parser_log("access_log_Jul95")
    Alexey Lavrenuke
    @direvius

    Задачка 3: топ 10 урлов

    Задание Найти 10 самых посещаемых урлов и число посещений для каждого из них

    Заготовка кода

    import re
    from collections import defaultdict
    
    regex = re.compile('([\w\-\.@\'*,:/#&]+) - - \[(.*?)\] "([A-Z]+)\s+(\S+).*" (\d+) (-|\d+)')
    def parse_line_re(line):
        try:
            return regex.match(line).groups()
        except AttributeError:
            return None
    
    # нас интересуют урлы без параметров, параметры могут быть и через хеш, и через вопрос
    # отделим их с помощью регэкспа
    delim = re.compile("[#?]")
    
    def count_urls():
        counts = defaultdict(int)
        with open("./access_log_Jul95", encoding="ascii", errors="replace") as datafile:
            for line in datafile:
                fields = parse_line_re(line)
                if fields:
                    uri = delim.split(fields[3])[0]
                    counts[uri] += 1
        return counts
    
    def top_ten():
        # ваш код здесь
        return []
    Andrey Yantsen
    @andrey-yantsen
    [('/images/NASA-logosmall.gif', 111388), ('/images/KSC-logosmall.gif', 89639), ('/images/MOSAIC-logosmall.gif', 60468), ('/images/USA-logosmall.gif', 60014), ('/images/WORLD-logosmall.gif', 59489), ('/images/ksclogo-medium.gif', 58802), ('/images/launch-logo.gif', 40871), ('/shuttle/countdown/', 40279), ('/ksc.html', 40232), ('/images/ksclogosmall.gif', 33585)]
    import ujson
    urls = ujson.loads(open('urls.json').read())
    print(list(sorted(urls.items(), key=lambda x: x[1], reverse=True))[:10])
    И ```
    Да блин
    %%bash
    pip3 install ujson
    :)
    Michael Penkov
    @mpenkov
    import json
    
    def top(urls):
        ordered = sorted(obj, key=lambda x: obj[x], reversed=True)
        return ordered[:10]
    
    with open("urls.json") as fin:
        obj = json.load(fin)
        print "\n".join(top(obj))
    Pavel
    @paveltyavin
    for i in range(10):
        url = max(a, key=a.get)
        print(url)
        a[url] = 0
    a = {
        "/images/landing-747.gif": 142,
    ...
    }
    Ivan Chernoff
    @vanadium23
    а вот так можно было решить ? (:
    cat NASA_access_log_Jul95 | grep -E " 200 ([0-9]+|-)" | grep -Eo "GET (.*?)" | awk '{print $2}' | sort -rn | uniq -c | sort -rn | head
    Alexey Lavrenuke
    @direvius
    import numpy as np    # numpy
    import pandas as pd   # pandas
    
    # альтернативная библиотека для визуализации
    # https://github.com/mwaskom/seaborn
    import seaborn as sns
    
    # подключаем графику прямо в браузер
    %matplotlib inline
    # основное понятие в Pandas -- DataFrame
    df = pd.DataFrame([
            ["Stuart Bloom", False, 50],
            ["Sheldon Cooper", True, 2000],
            ["Amy Farrah Fowler", False, 1200],
            ["Radjesh Koothrappali", False, 1000],
            ["Howard Wolowitz", False, 1500],
            ["Bernadette Rostenkowski", True, 2100],
            ["Penny", True, 5000],
            ["Leonard Hofstadter", True, 2500],
        ], columns="name pythonista salary".split())
    
    df
    Nikita Vdovushkin
    @briskly
    #briskly
    from collections import defaultdict
    from operator import itemgetter
    import re
    def parse_line(line):
        res = re.match(r"(.*)- - (\[.*\]) \"(\w+) (.+)( (.+))?\" (\d+) (\d+|-)", line)
        if res is None:
            return
        return res.groups()
    
    def parser_log(fn):
        d = defaultdict(int)
        for line in open(fn, encoding="ascii", errors="replace"):
        #for line in open(fn):
            res = parse_line(line)
            if res:
                url = res[3].rstrip(" HTTP/1.0").split("?")[0]
                d[url] += 1
        print (sorted(d.items(), key=itemgetter(1), reverse=True)[:20])
    
    
    parser_log("access_log_Jul95")
    Alexey Lavrenuke
    @direvius

    Задачка 4: Добавить фамилию

    Задание Добавить колонку с фамилией. Если фамилия двойная, в колонке должны быть обе ее части. Если фамилии нет, то в колонке должно быть None

    Заготовка кода

    df = pd.DataFrame([
            ["Stuart Bloom", False, 50],
            ["Sheldon Cooper", True, 2000],
            ["Amy Farrah Fowler", False, 1200],
            ["Radjesh Koothrappali", False, 1000],
            ["Howard Wolowitz", False, 1500],
            ["Bernadette Rostenkowski", True, 2100],
            ["Penny", True, 5000],
            ["Leonard Hofstadter", True, 2500],
        ], columns="name pythonista salary".split())
    
    # тут ваш код
    Andrey Yantsen
    @andrey-yantsen
    df['lastname'] = df['name'].apply(lambda x: '' if ' ' not in x else x.split(' ')[1])
    Artemiy
    @artemiy-rodionov
    def ln(i):                            
        names = i.split()
        try:
            return ' ' .join(names[1:])
        except IndexError:
            return names[0]
    df['last_name'] = df['name'].apply(ln)
    khudyakovavi
    @khudyakovavi
    df['last_name'] = df['name'].apply(lambda x: None if ' ' not in x else ' '.join(x.split()[1:]))
    Andrey Yantsen
    @andrey-yantsen
    df['lastname'] = df['name'].apply(lambda x: '' if ' ' not in x else ' '.join(x.split(' ')[1:]))
    Artemiy
    @artemiy-rodionov
    поправил код, чтобы двойные работали
    Alexey Lavrenuke
    @direvius
    regex = re.compile('([\w\-\.@\'*,:/#&]+) - - \[(.*?)\] "([A-Z]+)\s+(\S+).*" (\d+) (-|\d+)')
    delim = re.compile("[#?]")
    
    def parse_log_re(file):
        for line in file:
            try:
                # заодно отделим параметры от урла
                fields = regex.match(line).groups()
                uri_parts = delim.split(fields[3], 1)
                uri = uri_parts[0]
                if len(uri_parts) > 1:
                    params = uri_parts[1]
                else:
                    params = None
                yield list(fields) + [uri, params]
            except AttributeError:
                pass
    
    columns = "host ts method uri code size url params".split()
    with open("./access_log_Jul95", encoding="ascii", errors="replace") as datafile:
        df = pd.DataFrame.from_records(parse_log_re(datafile), columns=columns)
    df["size"] = pd.to_numeric(df["size"], errors='coerce')
    df["ts"] = pd.to_datetime(df["ts"], format="%d/%b/%Y:%H:%M:%S -0400")
    Pavel
    @paveltyavin
    Можно код гистограммы сюда?
    Alexey Lavrenuke
    @direvius
    # логарифмический масштаб по оси y
    fig, ax = sns.plt.subplots()
    fig.set_size_inches(16,10)
    df[["size"]].hist(bins=20, ax=ax)
    
    # задаем логарифмический размер
    ax.set_yscale("log")
    @vanadium23 на самом деле танкисты очень часто обходятся башем, грепом, awk и другими консольными утилитами и часто это быстрее, чем питон. Но мы же на pycon +)
    Shmele
    @butorov
    df[df['size'] > 2000000]
    khudyakovavi
    @khudyakovavi
    df.groupby('ts').size()
    Ivan Chernoff
    @vanadium23
    df.groupby('ts').size()
    печально писать в одно время пока не прилетело новые :(
    кажется, что с size лучше, потому что если предположить что метода нет, то rps будет посчитан неверно (:
    Alexey Lavrenuke
    @direvius
    size лучше, согласен +)
    khudyakovavi
    @khudyakovavi
    можно код для графика, пожалуйста?)
    Alexey Lavrenuke
    @direvius
    # добавим скользящее среднее, чтобы сгладить пики
    fig, ax = sns.plt.subplots()
    fig.set_size_inches(16,10)
    #rps.plot(ax=ax)
    
    # rolling сделает нам группы, используя скользящее окно, по которым можно считать разное
    roll = rps.rolling(window=600)
    roll.mean().plot(ax=ax, c="red")
    Ivan Chernoff
    @vanadium23
    Можно посмотреть топ урлов, возможно нужная большая точность по времени
    from datetime import datetime
    df[df['ts'] > datetime(1995, 7, 13)][df['ts'] < datetime(1995, 7, 15)].groupby('uri').count()
    xSnow
    @__int32_twitter
    This message was deleted
    Alex Belyaev
    @bwh1te
    /shuttle/countdown/video/livevideo.jpeg
    Ivan Chernoff
    @vanadium23
    то есть надо было по размеру искать?
    оу, всё сложнее
    Alexey Lavrenuke
    @direvius
    # функция для импорта сырого отчета phantom
    
    phout_columns = [
        'time', 'tag', 'interval_real',
        'connect_time', 'send_time',
        'latency', 'receive_time',
        'interval_event', 'size_out',
        'size_in', 'net_code', 'proto_code']
    
    def read_phout(filename):
        data = pd.read_csv(
            filename, sep='\t', names=phout_columns)
    
        # хитрые манипуляции с колонками
    
        # в логе есть время отправки и время выполнения запроса. Суммируем их и получается
        # время получения ответа - будем группировать по нему (заводим новую колонку)
        data['ts'] = data.time + data.interval_real / 1000000
        # округляем до секунды
        data['receive_sec'] = data.ts.astype(int)
        # и индексируем по этой секунде
        data.set_index(['receive_sec'], inplace=True)
        # для удобства посчитаем время ответа в миллисекундах
        data['rt_ms'] = data.interval_real / 1000
    
        return data
    phout1 = read_phout("phout_1.log")
    phout2 = read_phout("phout_2.log")
    Alexey Lavrenuke
    @direvius
    Ноутбук с воркшопа: https://clck.ru/9zsw3
    Michael Penkov
    @mpenkov
    @direvius Спасибо! До этого ни разу не приходилось иметь дело с pandas и jupyter, но очень понравилось. Буду дальше изучать.
    Alexey Lavrenuke
    @direvius
    @mpenkov пожалуйста! Рад, что было полезно.