本文以服务器日志分析为例,给大家展示真实场景中,怎么用pySpark去完成大数据的处理和分析的。
总述
这里的应用主要包括4部分:
Part 1: Apache Web服务器日志格式
Part 2: web服务器日志初步解析
Part 3: web服务器日志进一步解析和可视化
Part 4: 对返回404的结果做分析
part 1 Apache Web服务器日志格式
这里用到的服务器日志格式是 Apache Common Log Format (CLF)。简单数来,你看到的每一行都是如下的样式:
127.0.0.1 - - [01/Aug/1995:00:00:01 -0400] "GET /images/launch-logo.gif HTTP/1.0" 200 1839
一个详细一些的字段说明如下:
127.0.0.1
第一项 ,发起请求的客户端IP地址。-
第二项 ,空白,用占位符“-”替代,表示所请求的信息(来自远程机器的用户身份),不可用。-
第三项,空白,表示所请求的信息(来自本地登录的用户身份),不可用。[01/Aug/1995:00:00:01 -0400]
第四项,服务器端处理完请求的时间,具体细节如下:
[day/month/year:hour:minute:second timezone]
- day = 2 digits
- month = 3 letters
- year = 4 digits
- hour = 2 digits
- minute = 2 digits
- second = 2 digits
- zone = (+ | -) 4 digits
"GET /images/launch-logo.gif HTTP/1.0"
第五项,客户端请求字符串的第一行,包含3个部分。1)请求方式 (e.g.,GET
,POST
,HEAD
等.), 2)资源,3)客户端协议版本,通常是HTTP,后面再加上版本号200
第六项,服务器发回给客户端的状态码,这个信息非常有用,它告诉我们这个请求成功得到response(以2开头的状态码),重定向(以3开头的状态码),客户端引起的错误(以4开头的状态码),服务器引起的错误(以5开头的状态码)。更多的信息可以查看([RFC 2616]).1839
第七项,这个数据表明了服务器返回的数据大小(不包括response headers),当然,如果没有返回任何内容,这个值会是”-” (也有时候会是0).
NASA-HTTP Web Server Log
这里的例子用到的是一份来自NASA的服务器日志,完整的数据及可以在这里 下载到,也可以到百度网盘下载(链接:https://pan.baidu.com/s/1mi04sys 密码:3max)。
解析日志中的每一行
写一个python的正则表达式,抽取log中不同部分的信息。然后再对时间字段进行一些解析和处理。
from pyspark import SparkContext
sc = SparkContext('local', 'pyspark')
# 用于抽取信息的正则表达式
#127.0.0.1 - - [01/Aug/1995:00:00:01 -0400] "GET /images/launch-logo.gif HTTP/1.0" 200 1839
APACHE_ACCESS_LOG_PATTERN = '^(\S+) (\S+) (\S+) \[([\w:/]+\s[+\-]\d{
4})\] "(\S+) (\S+)\s*(\S*)" (\d{
3}) (\S+)'
import re
import datetime
from pyspark.sql import Row
month_map = {
'Jan': 1, 'Feb': 2, 'Mar':3, 'Apr':4, 'May':5, 'Jun':6, 'Jul':7,
'Aug':8, 'Sep': 9, 'Oct':10, 'Nov': 11, 'Dec': 12}
def parse_apache_time(s):
""" Convert Apache time format into a Python datetime object
Args:
s (str): date and time in Apache time format
Returns:
datetime: datetime object (ignore timezone for now)
"""
return datetime.datetime(int(s[7:11]),
month_map[s[3:6]],
int(s[0:2]),
int(s[12:14]),
int(s[15:17]),
int(s[18:20]))
def parseApacheLogLine(logline):
""" Parse a line in the Apache Common Log format
Args:
logline (str): a line of text in the Apache Common Log format
Returns:
tuple: either a dictionary containing the parts of the Apache Access Log and 1,
or the original invalid log line and 0
"""
match = re.search(APACHE_ACCESS_LOG_PATTERN, logline)
if match is None:
return (logline, 0)
size_field = match.group(9)
if size_field == '-':
size = int(0)
else:
size = int(match.group(9))
return (Row(
host = match.group(1),
client_identd = match.group(2),
user_id = match.group(3),
date_time = parse_apache_time(match.group(4)),
method = match.group(5),
endpoint = match.group(6),
protocol = match.group(7),
response_code = int(match.group(8)),
content_size = size
), 1)
初始化RDD并进行相应操作
下面我们可以用web日志文件初始化一个RDD,然后使用刚才的操作做解析了。