课程:《Python程序设计》
班级: 2013
姓名: 徐源
学号:20201324
实验教师:王志强
实验日期:2021年6月23日
必修/选修: 公选课
下图为我用自己的程序生成的歌曲海报之一
功能的实现分两步走,先爬虫得到歌单和歌曲信息,再利用这些信息生成海报
打开页面->F12->Network->XHR
找到client_search,点开,依次点击data->song->list->0,找到歌单上第一首歌的name:七里香
说明这一部分有我们想要的数据,Headers->Request URL,编写代码
代码如下
import requests res_music = requests.get('https://c.y.qq.com/soso/fcgi-bin/client_search_cp?ct=24&qqmusic_ver=1298&new_json=1&remoteplace=txt.yqq.song&searchid=60997426243444153&t=0&aggr=1&cr=1&catZhida=1&lossless=0&flag_qc=0&p=1&n=20&w=%E5%91%A8%E6%9D%B0%E4%BC%A6&g_tk=5381&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0') json_music = res_music.json()
分析知data是XHR的一个键,其对应的值也是一个字典;song是该字典的一个键,键song对应的值又是一个字典;list又是这个字典的一个值,其对应的值是一个列表,列表中的每一个元素都是一个字典,在每个字典里,键name的值即歌曲名,所以通过嵌套来获取歌曲名
代码如下
list_music = json_music['data']['song']['list'] # list_music是一个列表,又嵌套了字典 for music in list_music: # 以name为键,查找歌曲名 print(music['name']) # 查找专辑名 print('所属专辑:'+music['album']['name']) # 查找播放时长 print('播放时长:'+str(music['interval'])+'秒') # 查找播放链接 print('播放链接:https://y.qq.com/n/yqq/song/'+music['mid']+'.html') # 查找发布时间 print('发布时间:'+str(music['time_public'])) print('\n\n')
运行结果
OpenCV不能显示中文字符,且难以控制文字位置。因此我对比性能后在OpenCV和PIL中选择了后者。
安装库:pip install Pillow
调用库函数:from PIL import Image, ImageDraw, ImageFont
对照QQ音乐页面显示的歌名,手动搜索图片作为海报底板,记得要将图片命名为歌曲名,并保存为png格式。这样程序运行时就知道"歌曲名.png"就是我们为《歌曲名》准备的底板,从而实现一键批量处理
如何将jpg格式的图片转换成png格式
img = title+".png" # 图片底板 new_img = "final_"+title+".png" # 生成的海报
为方便演示,我将代码修改为for music in list_music[0:3]:
,仅为爬取到的前三首歌制作海报
setFont = ImageFont.truetype('C:/Windows/Fonts/STXINWEI.TTF', 20)
两个参数分别为字体在电脑中的路径和字体大小;
颜色用CSS颜色或直接color = "black"均可
我使用了两种方式写入:
① 单独写入一行字符
draw.text(x,y), information, font=setFont, fill="#000000", direction=None)
在底板上坐标(x,y)处开始写
information是要写入的内容,必须是字符型
② 将列表中的元素一行一行地打印出来
summary_y = 0 summary_line = 50 summary = ['所属专辑:'+'《' + music['album']['name'] + '》', '歌曲时长:'+str(music['interval'])+'秒','歌手:周杰伦','发布时间:'+str(music['time_public'])] for num, one in enumerate(summary): y = summary_start_y - num * summary_line summary_num = num + 1 draw.text((summary_x, height - y), u'%s. %s' % (summary_num, one), color, font)
这样可以自动换行和标号,行距一致,方便快捷,强烈推荐!
image.save(new_img, 'png')
做完一定要save一下,否则你会发现程序不报错,debug也没有问题,但就是没有你想要的海报(不要问我是怎么知道的/(ㄒoㄒ)/~~)
代码如下(关键代码的功能已注释)
# 图片名称 img = title+".png" # 图片模板 new_img = "final_"+title+".png" # 生成的图片 # 设置字体样式 font_type = "C:/Windows/Fonts/STXINWEI.TTF" font_medium_type = "C:/Windows/Fonts/STKAITI.TTF" header_font = ImageFont.truetype(font_type, 55) title_font = ImageFont.truetype(font_type, 45) font = ImageFont.truetype(font_medium_type, 20) # ImageFont.truetype第一个参数为字体,第二个为字体大小 color = "#000000" # 打开图片 image = Image.open(img) draw = ImageDraw.Draw(image) width, height = image.size # 获取原图像的宽和高,并保持最终海报的大小与之一致 # 写入header header_x = 40 header_y = 650 # 数字越小,字在图片上的位置越偏下 draw.text((header_x, height - header_y), u'%s' % header, color, header_font) # 写入标题 title_x = header_x title_y = header_y - 80 draw.text((title_x, height - title_y), u'%s' % title, color, title_font) # 写入歌曲信息 summary_x = title_x summary_start_y = title_y - 150 # title后面减的越多,字越偏下 summary_y = 0 summary_line = 50 information = '歌曲信息' setFont = ImageFont.truetype('C:/windows/fonts/STXINGKA.TTF', 25) draw.text((summary_x, height - summary_start_y-40), information, font=setFont, fill="#000000", direction=None) for num, one in enumerate(summary): y = summary_start_y - num * summary_line summary_num = num + 1 draw.text((summary_x, height - y), u'%s. %s' % (summary_num, one), color, font) # 写入链接 write_x = summary_x write_y = title_y - 400 write_line = 40 information = '播放链接:' setFont = ImageFont.truetype('C:/windows/fonts/STXINGKA.TTF', 25) draw.text((write_x, height - write_y), information, font=setFont, fill="#000000", direction=None) draw.text((write_x, height - write_y + write_line), writes, font=font, fill="#0000ff", direction=None) # 生成图片 image.save(new_img, 'png')
运行结果
OSError: cannot open resource
Python在图片中添加文字的两种方法
python PIL图像处理-图片上添加文字
Windows字体文件存放位置
如何将jpg格式的图片转换成png格式
码云链接:https://gitee.com/xu-yuan-20201324/python_use/blob/main/Socket_test/crawler_homework.py
操作视频已录制并发送至指定邮箱
我之所以报名python程序设计课是因为优秀学长学姐的强烈推荐。大一菜狗,网上选课时紧张到手一直在抖,系统一开放,我第一时间狂点python,抢到的那一刻当场开心到不能自已。
这门课带给了我什么?——它真的让我吃了很多苦,这学期我一直严格按照王老师“今日事,今日毕”的理念要求自己,作业一定要当天晚上就做,做不完就熬夜继续做。我的天赋和基础委实都很一般,以至于这学期90%以上的作业都是半夜提交的。做实验三时,因为第一次接触密码方面的知识,操作不规范,外加以前的种种问题相继暴露,我的电脑不幸经历了一波猛烈的故障o(TヘTo),导致这学期所有的python文件、之前做过的作业和实验报告、精心整理的课堂笔记,统统从本地清零了,码云仓库也被清空了。真的算得上是我遇到的最大的打击,那天我对自己说:“想哭就哭吧”,但发了很久的呆,最后还是程序从头重编,实验报告从零重写,然后,就这么过去了。
如果能重新做一次选择,我想,我还是会义无反顾。python程序设计课不仅提高了我的编程能力,加深了我对c语言等专业课内容的认识,也给了我一个机会,让我在探索新世界的过程中不断磨砺与成长。遇到问题时,学会问百度,学会总结经验,这是一种能力。如今的我,可以冷静地拆解问题、建立思路、动手实现,能静得下心来分析以前看一眼就觉得头大的网络开源代码,能在碰壁时心态平和地从新来过,这些能力放在任何领域都是宝贵的财富。
如果说有什么小建议的话,希望老师把函数、文件处理、爬虫等部分,结合具体例子,讲得再详细些吧。感觉前面简单的知识讲得很细,到了后面较难的部分反而不如前面细致了,也可能是我的理解能力跟不上了,嘿嘿嘿。这些部分的资源也请老师提前放到云班课上吧,课程刚开始时时间比较充足,后面可能没时间看了,不想浪费好资源。
最后,真诚感谢王老师一学期的精心指导,真的收获满满!