11.网页数据解析
# 导入库
import requests # 用于发出HTML请求
from bs4 import BeautifulSoup # 用于HTML格式化处理
import pandas as pd # 格式化数据
class WebParse:
# 初始化对象
def __init__(self, headers):
self.headers = headers
self.article_list = []
self.home_page = 'http://www.dataivy.cn/'
self.nav_page = 'http://www.dataivy.cn/page/{0}/'
self.art_title = None
self.art_time = None
self.art_cat = None
self.art_tags = None
# 获取页面数量
def get_max_page_number(self):
res = requests.get(self.home_page, headers=self.headers) # 发送请求
html = res.text # 获得请求中的返回文本信息
html_soup = BeautifulSoup(html, "html.parser") # 建立soup对象
page_num_code = html_soup.findAll('a', attrs={"class": "page-numbers"})
num_sets = [re.findall(r'(\d+)', i.text)
for i in page_num_code] # 获得页面字符串类别
num_int = [int(i[0]) for i in num_sets if len(i) > 0] # 获得数值页码
return max(num_int) # 最大页码
# 获得文章列表
def find_all_articles(self, i):
url = self.nav_page.format(i)
res = requests.get(url, headers=headers) # 发送请求
html = res.text # 获得请求中的返回文本信息
html_soup = BeautifulSoup(html, "html.parser") # 建立soup对象,用于处理HTML
self.article_list = html_soup.findAll('article')
# 解析单文章
def parse_single_article(self, article):
self.art_title = article.find('h2', attrs={"class": "entry-title"}).text
self.art_time = article.find('time', attrs={
"class": {"entry-date published", "entry-date published updated"}}).text
self.art_cat = article.find('a', attrs={"rel": "category tag"}).text
tags_code = article.find('span', attrs={"class": "tags-links"})
self.art_tags = '' if tags_code is None else WebParse._parse_tags(self, tags_code)
# 内部用解析tag函数
def _parse_tags(self, tags_code):
tag_strs = ''
for i in tags_code.findAll('a'):
tag_strs = tag_strs + '/' + i.text
return tag_strs
# 格式化数据
def format_data(self):
return [self.art_title,
self.art_time,
self.art_cat,
self.art_tags]
if __name__ == '__main__':
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36'} # 定义头信息
data_cols = ['title', 'time', 'cat', 'tags']
app = WebParse(headers)
max_num = app.get_max_page_number()
data_list = []
for ind in range(max_num):
app.find_all_articles(ind + 1) # ind从0开始,因此要加1
for article in app.article_list:
app.parse_single_article(article)
data_list.append(app.format_data())
data_pd = pd.DataFrame(data_list, columns=data_cols)
print(data_pd.head(2))
12.网络用户日志解析
# 导入库
import gzip
import re
import time
# 判断是否为爬虫记录
def is_spider(log_record, spiders):
detect_result = [True if log_record.find(spider) == -1 else False for spider in spiders]
is_exist = True if all(detect_result) else False
return is_exist
# 判断是否为UA记录
def is_ua_record(log_record):
is_ua = True if log_record.find('GET /__ua.gif?') != -1 else False
return is_ua
# 解析每条日志数据
def split_ua_data(line):
# 定义不同日志分割的正则表达式
ip_pat = '[\d.]*' # 定义IP规则,例如203.208.60.230
time_pat = '\[[^\[\]]*\]' # 定义时间规则,例如[02/Mar/2016:14:00:23 +0800]
request_pat = '\"[^\"]*\"' # 定义请求规则
status_pat = '\d+' # 定义返回的状态码规则,例如200
bytes_pat = '\d+' # 返回的字节数,例如326
refer_pat = '\"[^\"]*\"' # 定义refer规则
user_agent_pat = '\"[^\"]*\"' # 定义user agnet规则
# 原理:主要通过空格和-来区分各不同项目,各项目内部写各自的匹配表达式
re_pattern = re.compile('(%s)\ -\ -\ (%s)\ (%s)\ (%s)\ (%s)\ (%s)\ (%s)' % (
ip_pat, time_pat, request_pat, status_pat, bytes_pat, refer_pat, user_agent_pat),
re.VERBOSE) # 完整表达式模式
matchs = re_pattern.match(line) # 匹配
if matchs != None: # 如果不为空
allGroups = matchs.groups() # 获得所有匹配的列表
return allGroups[0], allGroups[1], allGroups[2], allGroups[3], allGroups[4], allGroups[5], allGroups[6]
else: # 否则返回空
return '', '', '', '', '', '', ''
# 读取日志数据
def get_ua_data(file, spiders):
ua_data = []
with gzip.open(file, 'rt') as fn: # 打开要读取的日志文件对象
content = fn.readlines() # 以列表形式读取日志数据
for single_log in content: # 循环判断每天记录
rule1 = is_spider(single_log, spiders)
rule2 = is_ua_record(single_log)
if rule1 and rule2: # 如果同时符合2条规则,则执行
ua_data.append(split_ua_data(single_log))
ua_pd = pd.DataFrame(ua_data)
return ua_pd
# 主程序
if __name__ == '__main__':
file = 'dataivy.cn-Feb-2018.gz' # 定义原始日志的文件名
spiders = [
'AhrefsBot',
'archive.org_bot',
'baiduspider',
'Baiduspider',
'bingbot',
'DeuSu',
'DotBot',
'Googlebot',
'iaskspider',
'MJ12bot',
'msnbot',
'Slurp',
'Sogou web spider',
'Sogou Push Spider',
'SputnikBot',
'Yahoo! Slurp China',
'Yahoo! Slurp',
'YisouSpider',
'YodaoBot',
'bot.html'
]
ua_pd = get_ua_data(file, spiders)
ua_pd.columns = ['ip_add', 'requet_time', 'request_info', 'status', 'bytes_info', 'referral', 'ua']
output_file = 'ua_result_{0}.xlsx'.format(time.strftime('%Y%m%d%H%M%S', time.localtime(time.time())))
ua_pd.to_excel(output_file, index=False)
print('excel file {0} generated!'.format(output_file))
13.图像的基本预处理
import cv2 # 导入图像处理库
import numpy as np # 导入numpy库
from matplotlib import pyplot as plt # 导入展示库
# 展示图像模块
def img_show(img_name, img):
cv2.imshow(img_name, img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 原始图像
img_file = 'sudoku.png' # 定义原始数据文件
img = cv2.imread(img_file) # 以彩色模式读取图像文件
rows, cols, ch = img.shape # 获取图像形状
img_show('raw img', img) # 展示彩色图像
# 图像缩放
img_scale = cv2.resize(img, None, fx=0.6, fy=0.6, interpolation=cv2.INTER_CUBIC) # 图像缩放
img_show('scale img', img_scale) # 展示缩放后的图像
# 图像平移
M = np.float32([[1, 0, 100], [0, 1, 50]]) # 定义平移中心
img_transform = cv2.warpAffine(img, M, (cols, rows)) # 平移图像
img_show('transform img', img_transform) # 展示平移后的图像
# 图像旋转
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 45, 0.6) # 定义旋转中心
img_rotation = cv2.warpAffine(img, M, (cols, rows)) # 第一个参数为旋转中心,第二个为旋转角度,第三个为旋转后的缩放因子
img_show('rotation img', img_rotation) # 展示旋转后的图像
# 透视变换
pts1 = np.float32([[76, 89], [490, 74], [37, 515], [520, 522]]) # 定义变换前的四个校准点
pts2 = np.float32([[0, 0], [300, 0], [0, 300], [300, 300]]) # 定义变换后的四个角点
M = cv2.getPerspectiveTransform(pts1, pts2) # 定义变换中心点
img_perspective = cv2.warpPerspective(img, M, (300, 300)) # 透视变换
img_show('perspective img', img_perspective) # 展示透视变换后的图像
# 转换为灰度图像
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 图像转灰度
img_show('gray img', img_gray) # 展示灰度图像
# 边缘检测
img_edges = cv2.Canny(img, 100, 200) # 检测图像边缘
img_show('edges img', img_edges) # 展示图像边缘
# 图像二值化
ret, th1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY) # 简单阀值
th2 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11,
2) # 自适应均值阀值
th3 = cv2.adaptiveThreshold(img_gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11,
2) # 自适应高斯阀值
titles = ['Gray Image', 'Global Thresholding (v = 127)',
'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding'] # 定义图像标题
images = [img_gray, th1, th2, th3] # 定义图像集
for i in range(4):
plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray') # 以灰度模式展示每个子网格的图像
plt.title(titles[i]) # 设置每个自网格标题
plt.xticks([]), plt.yticks([]) # 设置x轴和y轴标题
# 图像平滑
kernel = np.ones((5, 5), np.float32) / 25 # 设置平滑内核大小
img_smoth_filter2D = cv2.filter2D(img, -1, kernel) # 2D卷积法
img_smoth_blur = cv2.blur(img, (5, 5)) # 平均法
img_smoth_gaussianblur = cv2.GaussianBlur(img, (5, 5), 0) # 高斯模糊
img_smoth_medianblur = cv2.medianBlur(img, 5) # 中值法
titles = ['filter2D', 'blur', 'GaussianBlur', 'medianBlur'] # 定义标题集
images = [img_smoth_filter2D, img_smoth_blur, img_smoth_gaussianblur, img_smoth_medianblur] # 定义图像集
for i in range(4):
plt.subplot(1, 4, i + 1),
plt.imshow(images[i], 'gray') # 以灰度模式展示每个子网格的图像
plt.title(titles[i]) # 设置每个自网格标题
plt.xticks([]), plt.yticks([]) # 设置x轴和y轴标题
# 形态学处理
img2 = cv2.imread('j.png', 0) # 以灰度模式读取图像
kernel = np.ones((5, 5), np.uint8) # 设置形态学处理内核大小
erosion = cv2.erode(img2, kernel, iterations=1) # 腐蚀
dilation = cv2.dilate(img2, kernel, iterations=1) # 膨胀
plt.subplot(1, 3, 1), plt.imshow(img2, 'gray') # 设置自网格1图像
plt.subplot(1, 3, 2), plt.imshow(erosion, 'gray') # 设置自网格2图像
plt.subplot(1, 3, 3), plt.imshow(dilation, 'gray') # 设置自网格3图像
14.图像的基本预处理
# 导入库
import pandas as pd
import jieba # 结巴分词
from sklearn.feature_extraction.text import TfidfVectorizer # 基于TF-IDF的词频转向量库
# 分词函数
def jieba_cut(string):
return list(jieba.cut(string)) # 精确模式分词
# 读取自然语言文件和停用词
with open('text.txt', encoding='utf8') as fn1, open('stop_words.txt', encoding='utf8') as fn2:
string_lines = fn1.read()
stop_words = fn2.read()
string_lines = string_lines.split('\n')
stop_words = stop_words.split('\n')
# 中文分词
seg_list = list(map(jieba_cut, string_lines)) # 存储所有分词结果
for i in range(3): # 打印输出第一行的前5条数据
print(seg_list[1][i])
# word to vector
vectorizer = TfidfVectorizer(stop_words=stop_words, tokenizer=jieba_cut) # 创建词向量模型
vector_value = vectorizer.fit_transform(string_lines).toarray() # 将文本数据转换为向量空间模型
vector = vectorizer.get_feature_names() # 获得词向量
vector_pd = pd.DataFrame(vector_value, columns=vector) # 创建用于展示的数据框
print(vector_pd.head(1)) # 打印输出第一条数据