心得
七天虽短,但是在知识迅速增加的今天显得十分必要。七天的课程总体来说,
阶段性的进步
让我们有机会在短时间内接触到先进的知识体系。这离不开百度paddlepaddle的努力,课程阶梯难度的设置效果很好,作业反馈体系也很充分,主教班班老师都是超级好(吹爆xxxxxxxxxxx)。Paddle-hub的推出真的让我感觉paddle很有希望。
给后来者的建议是:看直播紧跟老师的脚步,多看群里讨论,充分利用paddle给的demo资源,有时候做一下代码的搬运工的确是可以提高效率。实战就是实战,不是考验你是否能自己写出来。而是看你如何利用别人的成果改善后创新。
总述一下7天课程的流程:
python基础,python爬虫基础爬取选手信息,matplotlib对爬取的数据进行分布上的可视化,paddlehub自制数据集选手分类,大作业完成评论内容的分析、绘制词云、审核内容。虽然是阶梯性的进步,但是有个小的建议给paddle:可以适当延长下训练营的周期(不过感觉7天很合适,可以考虑难度分级)。其实感觉如果完全没基础的话7天打卡很难跟下来。
之后话不多说,进行技术内容上的分析。
技术内容分析:
Day1
个人认为就是扫盲,剔除完全不想学习一门新语言的同学。但也考验一部分细节吧,或者根本称不上细节的基本操作。没什么好讲,直接上代码。
def table():
#在这里写下您的乘法口诀表代码吧!
for i in range(0, 10):
for j in range(1, i+1):
print('{}*{}={:<4}'.format(j, i, i*j), end='')
print('')
if __name__ == '__main__':
table()
#导入OS模块
import os
#待搜索的目录路径
path = "Day1-homework"
#待搜索的名称
filename = "2020"
#定义保存结果的数组
result = []
def findfiles():
#在这里写下您的查找文件代码吧!
for relpath, dirs, files in os.walk(path):
for name in files:
if filename in name:
full_path = os.path.join(relpath, name)
result.append(full_path)
for i in range(0, len(result)):
print([i+1, result[i]])
if __name__ == '__main__':
findfiles()
Day2
爬虫基本的操作,requests,BeautifuSoup,感觉模式性都十分强,直接套用模板即可。之前在群里看到有人爬了2万多张,有点可笑。当然本人第一次也是这种傻,本质上就是没有清空你保存图片链接的列表,仅此而已。
要弄清楚是根据每个明星生成的链接的列表
,生成完直接下载,
下载完到下一个明星时记得清空就好
。上代码:
def crawl_pic_urls():
'''
爬取每个选手的百度百科图片,并保存
'''
with open('work/'+ today + '.json', 'r', encoding='UTF-8') as file:
json_array = json.loads(file.read())
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
}
count=0
for star in json_array:
pic_urls=[]
name = star['name']
link = star['link']
#!!!请在以下完成对每个选手图片的爬取,将所有图片url存储在一个列表pic_urls中!!!
response = requests.get(link, headers=headers) # 使用headers避免访问受限
soup = BeautifulSoup(response.content, 'lxml')
tables=soup.find_all('div',class_="summary-pic")
#print(tables)
for table in tables:
Ahref=table.a['href']
album_url='https://baike.baidu.com'+Ahref
response = requests.get(album_url, headers=headers)
soup = BeautifulSoup(response.content, 'lxml')
pic_div=soup.find('div',class_="pic-list")
img_album=pic_div.find_all('img')
for img in img_album:
pic_urls.append(img['src'])
#!!!根据图片链接列表pic_urls, 下载所有图片,保存在以name命名的文件夹中!!!
down_pic(name,pic_urls)
Day3
任务就是画出体重分布的饼图,前三天我也没看视频,都是自己上网找找文档和现成的代码。“
我们不做代码的生产者,我们是代码的搬运工
”说的就是我,毕竟有学校任务压在头上,不能只顾这边。建议就是:大概理解为什么这么些,具体细节看文档,
一定要学会看文档
!贴代码:
%matplotlib inline
with open('data/data31557/20200422.json', 'r', encoding='UTF-8') as file:
json_array = json.loads(file.read())
countA=countB=countC=countD=0
for star in json_array:
weight=star['weight']
weight=int(weight[0:2])
if weight in range(30,46):
countA+=1;
elif weight in range(46,51):
countB+=1;
elif weight in range(51,56):
countC+=1;
else:
countD+=1;
weight_list=[countA,countB,countC,countD]
labels=['<=45kg','45~50','50~55','>55']
colors=['green','orange','blue','red']
plt.pie(weight_list,labels=labels,colors=colors,
labeldistance = 1.1,autopct = '%3.1f%%',shadow = False,
startangle = 90,pctdistance = 0.6)
plt.axis('equal')
这里插一句:每天学的真的是会作用到最后一天的大作业,尤其是今天的matplotlib中文字体的调整,最后一天的第一道坎就是这样,卡住了不少人。但是好多人不知道解决方法就在第三天写好的代码里面。用这些虚拟环境和别人写好的,不要无脑的运行,好歹看一下做了什么,有个印象。
Day4
就是
paddlehub
的简单应用,教你自定义数据集。这种预训练好的模型其实非常适合我们非研究型人员使用,提高了效率,减少了计算资源的消耗。Paddle也明白,这是
生态上的构建
,
这几天使用modelarts和hilens那边的实现也发现生态是个大问题
,
需要多少人员一点点地构建,我们这些使用者也终将有一天将要成为生态构筑的一员
。话这么多是因为day4我觉得不需要贴代码。用来填充字数(手动狗头)。
Day5
终于来到了
过五关斩六将的终极超级无敌大作业
。简单来讲就是把前几天所学综合,说是综合,还是让你把不同模块写出来,然后拼接一下就好。这里详细分析一下:
任务分解:爬取评论、清理数据、分词、词频统计、绘制词云、内容审查。
难点一
、
matplotlib中文字体
之前说了,解法就在day3藏着(明白着放着),看你是不是无脑了。我做的时候就直接把字体文件复制到matplot里面的ttf文件结束(具体看报错然后百度)。
(一种报错)
爆出上面的错误,请仔细读下,发现这个路径没有字体,所以解决方案就是直接喂给它
。
# 将字体文件复制到matplotlib字体路径
!cp simhei.ttf /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/ttf/
难点二、如何找评论接口、更新lastID多次请求评论
承认本人之前也不会,老师教了一个很好的方法:F12里面
可以多刷新几次看看,这里有什么
新出现的接口
。你一看有个带有
comment关键词的
(这个猜一猜,源码的编写者肯定不是命名妖怪,起一切所有人看不懂的。)
当然,也可以搬运哈哈哈。
老师总结道:爬虫有点类似于智斗,没有固定的套路,需要你一次次地尝试和分析
。真的十分确切,好玩。
评论的请求方式也十分特别:
是按照一页一页地请求。需要一次次更新lastID
,但这些老师都讲过,认真听嗷。
#请求爱奇艺评论接口,返回response信息
def getMovieinfo(url):
'''
请求爱奇艺评论接口,返回response信息
参数 url: 评论的url
:return: response信息
'''
session = requests.Session()
headers = {
"User-Agent": "Mozilla/5.0",
"Accept": "application/json",
"Referer": "http://m.iqiyi.com/v_19rqriflzg.html",
"Origin": "http://m.iqiyi.com",
"Host": "sns-comment.iqiyi.com",
"Connection": "keep-alive",
"Accept-Language": "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7,zh-TW;q=0.6",
"Accept-Encoding": "gzip, deflate"
}
response = session.get(url, headers=headers)
if response.status_code == 200:
return response.text
return None
#解析json数据,获取评论
def saveMovieInfoToFile(lastId,arr):
'''
解析json数据,获取评论
参数 lastId:最后一条评论ID arr:存放文本的list
:return: 新的lastId
'''
url ="https://sns-comment.iqiyi.com/v3/comment/get_comments.action?agent_type=118&agent_version=9.11.5&business_type=17&content_id=15068699100&page=&page_size=10&types=time&last_id="
url += str(lastId)
responesTxt = getMovieinfo(url)
responesJson = json.loads(responesTxt)
comments = responesJson['data']['comments']
for val in comments:
if 'content' in val.keys():
print(val['content'])
arr.append(val['content'])
lastId = str(val['id'])
return lastId
这里贴上处理特殊字符的代码,
正则化老师没有细讲
,据我的经验:
就是搬运,会用就好。
#去除文本中特殊字符
def clear_special_char(content):
'''
正则处理特殊字符
参数 content:原文本
return: 清除后的文本
'''
s = re.sub(r"</?(.+?)>| |\t|\r","",content)
s = re.sub(r"\n","",s)
s = re.sub(r"\*","\\*",s)
s = re.sub("[^\u4e00-\u9fa5^a-z^A-Z^0-9]","",s)
s = re.sub("[\001\002\003\004\005\006\007\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a]+","", s)
s = re.sub("[a-zA-Z]","",s)
s = re.sub("^d+(\.\d+)?$","",s)
return s
这里添加的两个词其实不建议这么做,我是偷懒仅加了两个偶像的名字,实际你可以选择从day3的json里面
保存下所有偶像的名字作为一个字典
,效率更高,效果更准确。(但谁让这两位粉丝比较狂热,我加两个就可以解决大部分问题了。)
def fenci(text):
'''
利用jieba进行分词
参数 text:需要分词的句子或文本
return:分词结果
'''
jieba.add_word('青你')
jieba.add_word('奥利给')
jieba.add_word('冲鸭')
jieba.add_word('虞书欣')
jieba.add_word('谢可寅')
seg_list= jieba.lcut(text, cut_all=False)
return seg_list
def stopwordslist(file_path):
'''
创建停用词表
参数 file_path:停用词文本路径
return:停用词list
'''
jieba.del_word('欣书')
stopwords = [line.strip() for line in open(file_path, 'r', encoding='utf-8').readlines()]
return stopwords
上面的代码需要你传入自己加入的
jieba停用词典
,
结构:一行一个词
(简单情况)。你可能发现我用了
dieba.del_word()
。这又是一个针对实际问题的调整,具体原因是因为有些粉丝盲目连刷偶像的名字
导致jieba分词出现问题,在词频表发现后选择从字典剔除该词
。
def movestopwords(sentence,stopwords,counts):
'''
去除停用词,统计词频
参数 file_path:停用词文本路径 stopwords:停用词list counts: 词频统计结果
return:None
'''
out=[]
#stopwords = stopwordslist('stopwords.txt') # 这里加载停用词的路径
for word in sentence:
if word not in stopwords:
if len(word)!=1:
counts[word]=counts.get(word,0)+1
return None
难点三、词频和词云部分
词频直接上代码:
def drawcounts(counts,num):
'''
绘制词频统计表
参数 counts: 词频统计结果 num:绘制topN
return:none
'''
x_axis=[]
y_axis=[]
c_order=sorted(counts.items(),key=lambda x:x[1],reverse=True)
for c in c_order[:num]:
x_axis.append(c[0])
y_axis.append(c[1])
#from matplotlib.font_manager import *
#myfont = FontProperties(fname='simhei.ttf')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] =False
plt.bar(x_axis,y_axis)
plt.show()
词云这部分作者也是全都不会,做了一次搬运工。
下图这个课程是官方的免费demo,NLP里面包含了词云
。搬运开始。不过这个demo给的是
lac实现分词的
,
具体情况具体修改
。
上代码:记得这里的map1.jpg是作为底的图,需要是白底。我用的小猪佩奇。
def drawcloud(word_f):
'''
根据词频绘制词云图
参数 word_f:统计出的词频结果
return:none
'''
cloud_mask=np.array(Image.open('map1.jpg'))
st=set(['东西','这是'])
wc=WordCloud(background_color='white',
mask=cloud_mask,max_words=150,
font_path='simhei.ttf',
min_font_size=10,
max_font_size=100,
width=400,
relative_scaling=0.3,
stopwords=st)
wc.fit_words(word_f)
wc.to_file('pic.png')
难点四、内容分析
这个应该也是讲过,记不清了。
使用hub中的porn_detection_lstm
,就吐槽paddle一句,porn啥意思???污言秽语吧,我来给你翻译一下。***
疑车无据
***。
def text_detection():
'''
使用hub对评论进行内容分析
return:分析结果
'''
porn_detection_lstm=hub.Module(name='porn_detection_lstm')
f=open('aqy.txt','r',encoding='utf-8')
for line in f:
if len(line.strip())==1:
continue
else:
test_text.append(line)
f.close()
input_dic={'text':test_text}
results=porn_detection_lstm.detection(data=input_dict,use_gpu=True,batch_size=1)
难点五、综合
#评论是多分页的,得多次请求爱奇艺的评论接口才能获取多页评论,有些评论含有表情、特殊字符之类的
#num 是页数,一页10条评论,假如爬取1000条评论,设置num=100
if __name__ == "__main__":
num=200
lastId='0'
arr=[]
with open('aqy.txt','a',encoding='utf-8') as f:
for i in range(num):
lastId=saveMovieInfoToFile(lastId,arr)
time.sleep(0.5)
for item in arr:
Item=clear_special_char(item)
if Item.strip()!='':
try:
f.write(Item+'\n')
except Exception as e:
print('special char')
f=open('aqy.txt','r',encoding='utf-8')
counts={}
for line in f:
words=fenci(line)
stopwords=stopwordslist('stopwords.txt')
movestopwords(words,stopwords,counts)
drawcounts(counts,10)
drawcloud(counts)
f.close()
display(Image.open('pic.png')) #显示生成的词云图像
结果如下:
六、内容审查
print(text_detection())
我是网管
。分析一条结果:
{'text': '谢可寅安琦虞书欣金子涵金子涵金子涵\n',
'porn_detection_label': 0,
'porn_detection_key':
'not_porn', 'porn_probs': 0.0001,
'not_porn_probs': 0.9999},
不是porn的概率最后给出了,
0.9999
。所以各位评论的时候小心了啊,会被查的,而且不是人工审查也可以嗷。
**
看到这了,麻烦留个赞或者提个建议呗~。
**