使用Python分析nginx日志

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介:

相信各位web后端的小伙伴对Nginx并不陌生,它是是一款面向性能设计的HTTP服务器,具有占有内存少,稳定性高等优势。所以很多个人网站,或者公司都会选择使用nginx作为服务器。在使用nginx的时候,每一个http请求都会产生一条日志,通过python分析日志我们可以清楚的了解网站的pv,uv等一些重要数据。
在服务器上我们通常使用logrotate来分割当天日志进行分析, 假设我当天结束分割出的的日志名字为log20101001.gz, 我们使用python的gzip库来读取这个压缩文件所以我们可以直接使用gzip库来打开文件

class an_log(object):

"""分析记录"""

    def __init__(self, filename):

        self.filename = filename

        self.picid_value = {}  # 一个用于存储所有pv,uv的字典



    def read_log(self):

        f = gzip.open(self.filename, 'r')

        for line in f:

            all_line = line.split()

一般一条nginx数据是这样的:

- 180.171.241.42 tb.lifehp.com - - [30/Oct/2016:23:58:03 +0800] "GET /index.php?m=newbar&a=operate&type=1&op=0&pa

看起来很杂乱无章,其实在分析pv,uv的时候我们着重需要的数据一共只有几个, 一个是ip:- 180.171.241.42
一个是参数:GET/index.php?m=newbar&a=operate&type=1&op=0&param=A000184&adsid=14&picid=141&time=1477842977818 HTTP/1.1, 一个是参数:GET/index.php?m=newbar&a=operate&type=1&op=0&param=A000184&adsid=14&picid=141&time=1477842977818 HTTP/1.1

每一个pv是由这些参数共同决定的,如果这些参数全部一致那就是一个pv,如果在参数一致的情况下ip从没出现过那就是一个uv, 所以我们只需要解析这些参数就可以

def read_log(self):

    f = gzip.open(self.filename, 'r')

    for line in f:

        all_line = line.split()

        try:

            a_line = dict(k.split('=') for k in all_line[8].split('&'))

            # 把所有参数解析到一个字典中,key为参数名,value为参数值类似于{type:1,param:A00184}

            ip = all_line[1]  # 获取ip

            media_id = a_line['param']

            op = a_line['op']

        except:

            continue

        try:

            adsid = a_line.get('adsid', 'null')

            picid = a_line.get('picid', 'null')

            area_name = a_line.get('area', 'null')

            os = a_line.get('os', '0')

        except:

            continue

使用try,except语句是因为很多日志并不是我们想要的类似于GET /small/v10/css/tlbs.css HTTP/1.1,当碰到这种类型的日志的时候,生成字典后通过try如果提取不到我们需要的参数就说明这条日志不需要,通过continue直接分下一条日志
pic = picid + media_id + adsid + op + area_name + os # 把参数组合生成唯一键名

如果键名存在就直接对pv,uv数值操作

if pic in  self.picid_value.keys():

    self.analysis_pv(pic)

    self.analysis_uv(pic, ip)

pv += 1 uv通过判断ip是否存在来判断是否加一

def analysis_pv(self, pic,):

    self.picid_value[pic]['pv'] += 1

    return self.picid_value

def analysis_uv(self, pic, ip):

    if ip not in self.picid_value[pic]['ip']:

        self.picid_value[pic]['uv'] += 1

        self.picid_value[pic]['ip'].add(ip)

    return self.picid_value

这里ip要使用set集合,如果使用列表 每次判断ip是否存在都要进行一次遍历时间复杂度为O(n),而集合判断是否存在时间复杂度为O(1)大大提高性能

如果键名不存在则进行初始化键

if pic in  self.picid_value.keys():

    self.analysis_pv(pic)

    self.analysis_uv(pic, ip)

else:

    self.picid_value[pic] = {}

    self.picid_value[pic]['picid'] = picid

    self.picid_value[pic]['adsid'] = adsid

    self.picid_value[pic]['media_id'] = media_id

    self.picid_value[pic]['op'] = op_name_dict[op]

    self.picid_value[pic]['os'] = os_name_dict[os]

    self.picid_value[pic]['pv'] = 0

    self.picid_value[pic]['uv'] = 0

    self.picid_value[pic]['ip'] =set()

    self.picid_value[pic]['area']=area_name_dict[area_name]

    self.analysis_pv(pic)

    self.analysis_uv(pic, ip)

最后返回一个字典

return self.picid_value

然后把分析的数据写入excel,这里我使用的是xlwt库

def write_excel(self, excel_name):

    workbook = xlwt.Workbook()

    worksheet = workbook.add_sheet('toolbar')

    cl_name = [u'媒体', 'op', 'os', 'adsid', 'picid', u'位置',  'pv', 'uv']

    c = 0

    for data in cl_name:

        worksheet.write(0, c, data)

        c += 1

    row_list = ['media_id', 'op', 'os', 'adsid', 'picid', 'area',  'pv', 'uv']

    r = 1



    for pic_name in self.picid_value:

        cl = 0

        for data_name in row_list:

            worksheet.write(r, cl, self.picid_value[pic_name][data_name])

            cl += 1

        r += 1

    workbook.save(excel_name)c

使用argparse添加一些参数说明,使用的时候直接 -h就能看到各种参数名字与作用

if __name__ == '__main__':

    parser = argparse.ArgumentParser('log statistic')

    parser.add_argument('-f', '--file', default=None, help='filename')

    args = parser.parse_args()

    log_value = an_log(args.file)

    if log_value:

        log_value.read_log()

        file_name1 = 'example2.xls'

        log_value.write_excel(file_name1)

也可以使用各种python数据分析库来进行分析,添加分析参数只需要在in_value方法中添加各种相应的参数字段就可以。水平有限,代码还有很多需要改进的地方,如果各位有什么好的想法和建议也欢迎反馈。点击阅读原文可访问作者博客。


原文发布时间为:2016-11-19 

本文作者:熊球

本文来自云栖社区合作伙伴“Python中文社区”,了解相关信息可以关注“Python中文社区”微信公众号

相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
相关文章
|
8天前
|
缓存 供应链 监控
1688item_search_factory - 按关键字搜索工厂数据接口深度分析及 Python 实现
item_search_factory接口专为B2B电商供应链优化设计,支持通过关键词精准检索工厂信息,涵盖资质、产能、地理位置等核心数据,助力企业高效开发货源、分析产业集群与评估供应商。
|
6天前
|
缓存 监控 算法
item_get - Lazada 商品详情详情接口深度分析及 Python 实现
Lazada商品详情接口item_get可获取商品全维度数据,包括价格、库存、SKU、促销及卖家信息,支持东南亚六国站点,适用于竞品监控、定价策略与市场分析,助力跨境卖家精准决策。
|
5天前
|
供应链 监控 算法
VVICitem_get - 根据 ID 取商品详情接口深度分析及 Python 实现
VVIC(搜款网)是国内领先的服装批发电商平台,其item_get接口支持通过商品ID获取详尽的商品信息,涵盖价格、规格、库存、图片及店铺数据,助力商家高效开展市场分析、竞品监控与采购决策。
|
5天前
|
缓存 算法 数据安全/隐私保护
VVICitem_search - 根据关键词取关键词取商品列表接口深度分析及 Python 实现
VVIC item_search接口支持关键词搜索服装商品,提供价格、销量、供应商等数据,助力市场调研与采购决策。
|
6天前
|
缓存 自然语言处理 算法
item_search - Lazada 按关键字搜索商品接口深度分析及 Python 实现
Lazada的item_search接口是关键词搜索商品的核心工具,支持多语言、多站点,可获取商品价格、销量、评分等数据,适用于市场调研与竞品分析。
|
8天前
|
自然语言处理 算法 数据安全/隐私保护
item_review - Lazada 商品评论列表接口深度分析及 Python 实现
Lazada商品评论接口(item_review)可获取东南亚多国用户评分、评论内容、购买属性等数据,助力卖家分析消费者偏好、优化产品与营销策略。
|
8天前
|
缓存 监控 算法
京东item_search_best 畅销榜接口深度分析及 Python 实现
京东item_search_best接口可实时获取京东各品类畅销商品排名、销量、价格等核心数据,支持多维度榜单分析与品牌竞品监控,助力商家精准选品、制定市场策略,全面把握消费趋势。
|
4月前
|
监控 容灾 算法
阿里云 SLS 多云日志接入最佳实践:链路、成本与高可用性优化
本文探讨了如何高效、经济且可靠地将海外应用与基础设施日志统一采集至阿里云日志服务(SLS),解决全球化业务扩展中的关键挑战。重点介绍了高性能日志采集Agent(iLogtail/LoongCollector)在海外场景的应用,推荐使用LoongCollector以获得更优的稳定性和网络容错能力。同时分析了多种网络接入方案,包括公网直连、全球加速优化、阿里云内网及专线/CEN/VPN接入等,并提供了成本优化策略和多目标发送配置指导,帮助企业构建稳定、低成本、高可用的全球日志系统。
615 54
|
9月前
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
257 9

推荐镜像

更多