python迷你项目学习
基于Python课老师布置的作业题目の学习存档。
一、统计中文文本词频,生成词云图
参考文章:
理论与实战:一篇看懂Python词云 - 牛牛巴士社区
wordcloud:自定义背景图片,生成词云-阿里云开发者社区
Python中jieba库和wordcloud词云库配合使用进阶,生成指定形状和颜色的词云图 - 知乎用到的库/模块:
jieba
:中文文本分割from collections import Counter
:统计词频numpy
、from PIL import Image
:对我们自己导入的背景图进行处理from wordcloud import WordCloud, ImageColorGenerator
:生成词云图
大致步骤:
- 文件读取(加上
encoding='utf-8'
),将要分析的文本 & 停用词各自读取到一个 str 中; - 用
jieba.cut()
分割,得到初步词表; - 去除停用词(包括标点、空格),将剩余的词汇加入新 list 中,得到最终词表;
- 用
Counter()
统计词频后,将 list 转换为 dict ; - 加载背景图后,用
numpy.array()
预处理背景图,然后用ImageColorGenerator()
提取图片颜色; - 用
WordCloud()
(记得在参数中指定上一步中提取的颜色 )生成词云对象,并用.generate_from_frequencies()
根据词频 dict 生成词云; - 最后用
.to_file()
生成词云图片。
- 文件读取(加上
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# 使用 conda install 的话,要在管理员终端中下载
from os import path
# 中文文本分词
import jieba
# 词频统计
from collections import Counter
# 生成词云
from wordcloud import WordCloud, ImageColorGenerator
# 图片处理
# imageio.imread('cat.jpg')
import numpy as np
# import matplotlib.pyplot as plt
# 相比上面的库,图像处理功能更强大
from PIL import Image
# 设置基本路径
d = path.dirname(__file__)
# 设置停用词表路径
stopword_path = path.join(d, 'stop_words_zh.txt')
# 读取停用词表
# Return a list of the lines in the string, breaking at line boundaries
with open(stopword_path, 'r', encoding='utf-8') as stopword_f:
stopword_list = stopword_f.read().splitlines()
# 设置要分析的文本路径
text_path = path.join(d, '杀人十角馆.txt')
# 读取文本
with open(text_path, 'r', encoding='utf-8') as text_f:
text = text_f.read()
# seg_list暂存jieba.cut初步分割后的词表
seg_list = jieba.cut(text, cut_all=False, HMM=True)
liststr = '/'.join(seg_list)
# 去除标点和停用词
wordlist = []
for i in liststr.split('/'):
# 去除文字前后空格
word = i.strip()
# 符合条件的词语加入列表(停用词表还是漏了很多词,不管了)
if not(word in stopword_list) and len(word)>1:
wordlist.append(word)
# 去停用词后,将列表转换为词频字典
frequency = dict(Counter(wordlist))
# 加载背景图
background_image = np.array(Image.open(path.join(d, 'image.jpg')))
# 提取图片颜色,设置词云颜色
bg_color = ImageColorGenerator(background_image, default_color=None)
# 生成词云
wc = WordCloud(
# 背景颜色
background_color='white',
# 背景图片
mask=background_image,
# 中文汉字显示
font_path='C:\Windows\Fonts\simhei.ttf',
# 最大词数
max_words=500,
# 自定义颜色后记得在参数中指定
color_func=bg_color
)
# 根据词频生成词云
wc.generate_from_frequencies(frequency)
# 生成图片
wc.to_file('output.png')
- 最终词云图:
- (因为停用词表和文本不太搭,去除效果不佳)
二、电影推荐系统(协同过滤算法)
参考文章:
协同过滤算法概述与python 实现协同过滤算法基于内容
协同过滤(cf)——usr-item和item-item介绍原创
DataFrame
对象数据去重:pandas: Get unique values and their counts in a column
ndarray
数组连接:NumPy: Concatenate arrays with np.concatenate, np.stack, etc.用到的库/模块:
sklearn
:高阶算法pandas
:数据分析(提供了数据结构DataFrame
和Series
)numpy
:数组、矩阵处理(提供了多维数组对象ndarray
)
名词解释:
- user - item/ user - base:对比用户间喜好的相似性。根据与目标用户喜好相似的用户,向目标用户推荐与其最相似用户的喜好物品。
- item - item/ item - base:综合不同用户对不同物品的评分,向目标用户推荐与其喜好相似的物品。
- 相似度计算:
- 欧式距离法(euclidean 系数法)
- p系数法(pearson 系数法)
pandas DataFrame
:一种方便的二维数据矩阵结构,pandas
中对其内置了很多方便的方法。详见:pandas DataFrame
大致步骤(我也不是很清楚):
- 定要素——确定参与偏好相似评价的各个要素;
- 读数据——用
pandas.read_csv()
, 将用户评分数据读取到DataFrame
对象中; - 数据处理——将
DataFrame
数据集转化为矩阵; - 计算相似度——确定相似度计算方法,求出两两主体之间的相似度,并存储为相似度矩阵;
- 以欧式距离法为例:用
sklearn.…….pairwise_distances()
计算两向量间距离;之后将距离转化为相似度,分别创建用户相似度矩阵 & 电影相似度矩阵
- 以欧式距离法为例:用
- 加权度——基于相似度和评价度量,为每个主体未评价过的对象计算推荐指数;
- 若采用 item - item 模式,则“剩余用户 sim * 各电影评分 = 各电影最终权重”
- 输出最终预测结果。
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
import os import numpy import pandas from sklearn import model_selection from sklearn.metrics.pairwise import pairwise_distances # 欧氏距离转化为相似度 def dis_to_sim(rating_matrix): for x in range(len(rating_matrix)): for y in range(len(rating_matrix[x])): rating_matrix[x][y] = 1 / (1 + rating_matrix[x][y]) return rating_matrix # 两种预测模式 def predict(user_id, ratings, similarity, type='user'): pred = 0 if type == 'item': weight_matrix = numpy.zeros_like(ratings) # 剩余用户 sim * 各电影评分 = 各电影权重 for r in range(len(ratings)): for s in range(len(similarity[user_id-1])): weight_matrix[r][s] = ratings[r][s] * similarity[user_id-1][s] # 对同一电影的所有用户权重:求和、取平均权重,即为该电影最终权重 # 计算沿指定轴 axis 的算术平均值,返回含指定轴平均值的 numpy 数组: axis=0为沿行,axis=1为沿列 mean_weight = weight_matrix.mean(axis=1) # 排除目标用户看过的(即用户评过分的)电影 movie_No = numpy.argmax(mean_weight) for i in range(len(mean_weight)): if ratings[user_id-1][movie_No] != 0: break numpy.delete(mean_weight, movie_No) movie_No = numpy.argmax(mean_weight) # 返回权重最高的电影の序号(即 numpy 数组下标加一) pred = movie_No + 1 elif type == 'user': # 对用户相似度矩阵排序后,取相似度最大的人(除开自己!于是使用切片 & 拼接) # 拼接 numpy 数组:https://stackoverflow.com/questions/9236926/concatenating-two-one-dimensional-numpy-arrays similar_user_array = numpy.concatenate((similarity[user_id-1][:user_id-2], similarity[user_id-1][user_id:]), axis=0) similar_user = numpy.argmax(similar_user_array) # 推荐相似的人看过 and 目标分析用户没看过的电影序号 movie_No = numpy.argmax(ratings[similar_user]) for i in range(len(ratings[similar_user])): if ratings[similar_user][movie_No] != 0 and ratings[user_id-1][movie_No] == 0: break numpy.delete(ratings[similar_user], movie_No) movie_No = numpy.argmax(ratings[similar_user]) # 返回权重最高的电影の序号(即 numpy 数组下标加一) pred = movie_No + 1 return pred # 输入用户 id user_id = int(input('输入用户id:')) # 生成训练、评估数据集 file_path = os.path.join('ml-100k', 'u.data') # 自定义列名 headers = ['user_id', 'movie_id', 'rating', 'timestamp'] # Read a comma-separated values (csv) file into DataFrame. df = pandas.read_csv(filepath_or_buffer=file_path, sep='\t', names=headers) # 统计用户 & 电影总数,创建 user-item 矩阵时使用 # 若数据集中包含 N/A 则使用 .nunique() 较佳 n_users = df.user_id.unique().shape[0] n_movies = df.movie_id.unique().shape[0] # 将 df 数据集转化为 user-item 矩阵 rating_matrix = numpy.zeros((n_users, n_movies)) # Iterate over DataFrame rows as namedtuples. for line in df.itertuples(): rating_matrix[line[1]-1, line[2]-1] = line[3] # 计算相似度,构造相似度矩阵:采用欧式距离 # 此方法采用向量数组或距离矩阵,并返回距离矩阵。 user_distance = pairwise_distances(rating_matrix, metric='euclidean') # 在 NumPy 中,矩阵对象有一个 .T 属性,用于返回矩阵的转置。 movie_distance = pairwise_distances(rating_matrix.T, metric='euclidean') # 距离转换为相似度:加一取倒 user_sim = dis_to_sim(user_distance) movie_sim = dis_to_sim(movie_distance) # 预测 # 根据(用户)对电影的评分推荐相似电影 item_prediction = predict(user_id, rating_matrix, movie_sim, type='item') # 根据相似用户推荐电影 user_prediction = predict(user_id, rating_matrix, user_sim, type='user') # 将电影序号和电影名对应为字典;使用.split('|')分割数据 movie_dict = {} # 编码问题:https://stackoverflow.com/questions/19699367/for-line-in-results-in-unicodedecodeerror-utf-8-codec-cant-decode-byte with open(os.path.join('ml-100k', 'u.item'), 'r', encoding='ISO-8859-1') as info_f: info_list = info_f.readlines() for str in info_list[:]: fields = str.split('|') movie_id = int(fields[0]) movie_title = (fields[1]) # 添加字典元素 movie_dict[movie_id] = movie_title # 输出推荐结果 print('为你推荐: ') print('猜你喜欢电影:《{}》'.format(movie_dict[item_prediction])) print('和你类似的用户也喜欢电影:《{}》'.format(movie_dict[user_prediction]))
三、b站视频信息爬取
b站 api 端口:
参考文章:
B站视频信息爬取教程 - 知乎
哔哩哔哩分区视频详细信息爬取(三连、播放量、标签)等_怎么根据bv号获得b站视频分类-CSDN博客
Python爬虫实战:爬取B站Top100视频,分析弹幕、播放量和分类并数据可视化 - 雨月空间站
【教程】如何获取B站用户Cookie | Jimmy’s TechBlog
【Python】大数据挖掘课程作业1——使用爬虫爬取B站评论、弹幕与UP主的投稿视频列表_数据挖掘_RM -RF /星-开放原子开发者工作坊需求:
这次的需求比较简单,只是传入一个视频 url ,返回 json 形式的视频信息数据即可。
用到的库/模块:
json
:json 格式转换re
:提供操作正则表达式的方法,用于筛选字符串元素requests
:发送 HTTP 请求、处理 HTTP 响应等
名词解释:
JSON
数据格式:类似Python
字典,包含可嵌套的键值对;引用值的方式也和字典类似。同时易于机器 & 人类理解而被广泛使用。(补充知识:JSON5
是一种基于JSON
的扩展格式,支持注释和其他一些增强功能。)- 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
data = { "name": "Alice", "age": 25, "isStudent": true, "courses": [ "Mathematics", "Computer Science" ], "address": { "street": "123 Main St", "city": "Wonderland", "zip": "12345" } } // 引用键值举例——注意 str 格式 data['name'] = 'Alice' data['courses'] = ['Mathematics', 'Computer Science']
正则表达式:用于字符串匹配和提取
re
库常用函数:Python 正则表达式:http://www.runoob.com/python/python-reg-expressions.html- 常见正则式规则:
字符匹配
.
:匹配除换行符外的任何单个字符。- 例子:
a.b
可以匹配aab
,acb
,a1b
等。
- 例子:
[ ]
:字符集,匹配方括号中的任意一个字符。- 例子:
[abc]
可以匹配a
,b
,c
。
- 例子:
[^ ]
:否定字符集,匹配不在方括号中的任意字符。- 例子:
[^abc]
可以匹配d
,e
,1
等。
- 例子:
\*
:匹配前面的字符零次或多次。- 例子:
a*
可以匹配 `,
a,
aa,
aaa` 等。
- 例子:
+
:匹配前面的字符一次或多次。- 例子:
a+
可以匹配a
,aa
,aaa
等。
- 例子:
?
:匹配前面的字符零次或一次。- 例子:
a?
可以匹配 `,
a`。
- 例子:
{n}
:匹配前面的字符恰好n次。- 例子:
a{3}
可以匹配aaa
。
- 例子:
{n,}
:匹配前面的字符至少n次。- 例子:
a{2,}
可以匹配aa
,aaa
,aaaa
等。
- 例子:
{n,m}
:匹配前面的字符至少n次,至多m次。- 例子:
a{2,4}
可以匹配aa
,aaa
,aaaa
。
- 例子:
特殊字符
\d
:匹配任何数字字符,相当于[0-9]
。- 例子:
\d
可以匹配0
,1
,2
等。
- 例子:
\D
:匹配任何非数字字符,相当于[^0-9]
。- 例子:
\D
可以匹配a
,b
,!
等。
- 例子:
\w
:匹配任何字母、数字或下划线字符,相当于[a-zA-Z0-9_]
。- 例子:
\w
可以匹配a
,1
,_
等。
- 例子:
\W
:匹配任何非字母、数字或下划线字符,相当于[^a-zA-Z0-9_]
。- 例子:
\W
可以匹配!
,@
,#
等。
- 例子:
\s
:匹配任何空白字符(空格、制表符、换行符等)。- 例子:
\s
可以匹配空格、制表符、换行符等。
- 例子:
\S
:匹配任何非空白字符。- 例子:
\S
可以匹配a
,1
,!
等。
- 例子:
边界匹配
^
:匹配字符串的开始。- 例子:
^abc
可以匹配以abc
开头的字符串。
- 例子:
$
:匹配字符串的结束。- 例子:
abc$
可以匹配以abc
结尾的字符串。
- 例子:
\b
:匹配单词边界。- 例子:
\bword\b
可以匹配word
,但不匹配wordy
。
- 例子:
\B
:匹配非单词边界。- 例子:
\Bword\B
可以匹配awordb
,但不匹配word
。
- 例子:
逻辑运算
|
:逻辑或,匹配左边或右边的表达式。- 例子:
a|b
可以匹配a
或b
。
- 例子:
()
:分组,组合多个字符作为一个整体进行匹配。- 例子:
(abc)
可以匹配abc
。
- 例子:
(?:...)
:非捕获组,不捕获匹配的文本,仅用于匹配。- 例子:
(?:abc)
匹配abc
但不捕获。
- 例子:
Cookie
:类似浏览器页面对用户信息的缓存,让网页能够更方便地向用户提供个性化服务 。防盗链
Referer
:用于告诉目标服务器,请求是从特定页面发起的;如果Referer
头指示请求不是来自允许的域名,请求可能会被服务器拒绝。
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import json
import re
import requests
# 如何获取自己的b站 cookie 见上面教程
user_cookie = "b站用户 cookie"
# b站 api 可能会更新变化,记得及时去上面的 github 库中校对最新 api 端口
info_api = f"https://api.bilibili.com/x/web-interface/view?bvid="
# 传入单个视频 url,返回视频基本信息
def get_biliinfo(bili_url):
# 用正则式从 url 中提取视频 BV 号
pattern = re.compile(r'/video/([a-zA-Z0-9]+)')
# 存储格式为列表
# 后面用循环主要是为了提取出列表中的字符串 bvid 元素。
bvids = pattern.findall(bili_url)
# 爬取视频信息(目前端口返回的数据中同时包含了视频基本信息、三连数、历史最高排名等)
header = {
# 伪装浏览器客户端(这里伪装的是 Edge 浏览器)
# 后面的数据:浏览器版本号
'User-Agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5735.110 Safari/537.36 Edg/114.0.1823.79",
# 防盗链:
'Referer': "https://www.bilibili.com/",
'Cookie': user_cookie
}
for bvid in bvids:
try:
response = requests.get(url=info_api+bvid, headers=header)
# 检查服务器是否接受请求,200则请求成功
print(response.status_code)
#返回json格式的视频信息数据
info_json = response.json()
except:
# 若上面的步骤没执行成功,则进入 except 版块
print('something goes wrong...')
# 这里因为需求比较简单,没有对视频数据进行进一步的筛选和分类
# 返回视频信息数据
return info_json
四、Python游戏版块
纯萌新去B站入门最佳(教程零门槛)!
日后经验 & 内容丰富了可能会单独分离出来。
pgzero (pygame zero)
pygame
基础:
图片绘制——
surface
对象、Rect
对象文字显示:
在 pygame 窗口上显示文本有 7 个基本步骤:
- 使用pygame的display.set_mode()方法创建一个显示表面对象。
- 使用 pygame 的 font.Font() 方法创建一个 Font 对象。
- 使用 pygame 字体对象的 render() 方法创建一个文本表面对象 iesurface 对象,在其中绘制文本。
- 使用 pygame 文本表面对象的 get_rect() 方法为文本表面对象创建一个矩形对象。
- 通过设置 pygame 矩形对象的 center 属性的值来设置矩形对象的位置。
- 使用 pygame 显示表面对象的 blit() 方法将文本表面对象复制到显示表面对象。
- 使用 pygame 的 display.update() 方法在 pygame 窗口上显示显示表面对象。
用法示例:
1 2 3 4 5 6 7 8 9
# 显示文字の字体 info_font = pygame.font.SysFont('arial', 30) # draw text on a new Surface text = info_font.render('Choose your Servant', True, WHITE) rec_text = text.get_rect(); rec_text.center = (400, 100) screen.blit(text, rec_text) # 显示变量的话,在更新变量后要记得更新文本 self.score_text = info_font.render('score:' + str(self.hero.score), True, WHITE)
What fonts can I use with pygame.font.Font? - Stack Overflow
键盘输入——
pygame.event.get()
碰撞检测:Rect 对象
python - How do I detect collision in pygame? - Stack Overflow
时间延迟:设置两个变量,使用时间差
获得时间:
Clock对象.get_time()
用法示例:
1 2 3 4 5 6 7
clock = pygame.time.Clock() # 老问题:边界用大于等于,而非直接等于 if self.spawn_timer >= 50000: self.new_enemy() # 计数器置0 self.spawn_timer = 0 self.spawn_timer += clock.get_time()
背景音乐 & 音效
- 背景音乐类:
pygame.mixer.music
- 音效类:
pygame.mixer.Sound
- 背景音乐类:
进阶(伪)——类封装:
入门认知:
Program Arcade Games With Python And Pygame:http://programarcadegames.com/index.php?chapter=introduction_to_classes&lang=en
Pygame Platformer Tutorial - Full Course - YouTube(太长了,先只看看大佬的代码风格)代码参考:github各路仓库——参考类划分 & 函数应用
matsrorbecker/pgzero_game: A simplified version of Space Invaders …
进阶:
使用 .json
文件存取游戏中数据
这一方面的知识,可参考 Unity 等的数据存取经验。
实现 RPG 游戏中对话文本打字显示的效果
How to animate scrolling text in Python! (Pygame typewriter style text animation)
补充条目(随缘看):
对话树
[制作分享] 游戏中的对话框制作
[原创发布]『又一』立绘对话框系统 for RMVA Ver 5.1.1 支持RGD!图片随机变化效果(可用于抽奖啥的)
1
2
3
screen.blit(pygame.image.load(food_images[random.randrange(0, len(food_images)-1)]).convert_alpha(), \
(700, 380, 100, 100))
pygame.display.flip()