人生第一篇!冲冲冲
在大一上通过学长的介绍认识到了CSDN并加入到今天也刚好是半年的时间,所以想着认认真真的写下我的第一篇博客,也算是对我学习生涯的一次成果验收。
项目来源
说来也是巧合,我是偶然看到学校兼职群里有个学姐发布了一个小兼职贴,是拿数据
简单询问之后,学姐的意思大概是:有这么一个网站
需要将里面的小学课程,点开就是这样
将小学里的,语文、数学、英语、英语PEP(三年级后才有)的每个课程视频点击开,这里我们随便点开一个
在这一页中需要我们拿的数据为
另外还有视频链接与视频封面链接(这里学姐也是非常热情的向我讲解了如何获取到这两个东西,包括:页面空白处右键选择查看网页源代码、Ctrl+F打开搜索框,将m3u8,,,,,,,,,,,,)
还让我把复制来的数据放到给定的excel中。
。
。
。
。
当时听学姐需求的时候我一脸懵逼呀,完事我一回过神来心想:这不就一简单爬虫吗?
。。。。。
。。。。
。。。
。。
。
OK,说干就干!
这活我接了!
梳理需求
首先我们反观需求,需要的数据都存在单个页面中,若要对单个页面请求,无疑请求量会很大,但像这种网站应该不会有反爬,大不了挂代理呗。这样思路就有了,先搞到每个小单页的url,再对url池挨个请求拿数据。
我们再观察一下这个网站,当我们点击更改年级、学科、单元时,整个网页并没有跳转,而是在原网页中动态加载出页面,这时我们大致就心里有谱,八九不离十是ajax。
按下F12,刷新页面,观察xhr和json一栏,果然有数据
我们直接进行全局搜索
随便找一个课程题目比如 我是中国人
然后搜索一下
这样数据包就被我们找到了。点开它,我们发现它的响应数据是一个庞大的json数据:caseJson。并且他是一个由字典列表循环嵌套起来的数据。
我们直接看到它的根部数据有一个caseCode的键,它的值是一串很诡异的代码。
这时!所有的感觉都回来了!真相只有一个!于是我去寻找这个名叫 千人糕 的课程小页。但怎么也找不到- -
坏了,难道这破json串的数据是无序的?
这种数据我咋用呀。
于是我怀着失落的心又回到network
不过,
这家伙属实是有点奇怪呀,咋还有一个jsondata,点进去瞅瞅。
这一瞅可要命了,终于被我找到!!!
不仅有casecode,而且自带单元名,还是有序的。
我们直接打开,我去上学了,这个单元
有三个课程,对应上面三个casecode,完美!
我们点开第一个”我是中国人“,发现他的网址就是由casecode拼接而成的
对应规则大致为:
url="https://tongbu.eduyun.cn/tbkt/tbkthtml/wk/weike/"+casecode[5]+"/"+casecode+".html"
OK,这样,大致思路就有了,让我们正式开始吧!
casecode获取
比较正常的思路是直接对我们确定的那个jsondata发送请求,然后把响应数据转化为我们python的list或者dict,但这里博主直接暴力获取!。。。。Ctrl c +Ctrl v
手动拼凑成一个list!就像这样哈哈哈
这些都是细节,大家不必在意,继续前进!
不断进行尝试,最后很容易弄清楚这个数据串的树状结构
(博主自认为已经尽力~)
通过字典与列表的层层嵌套切片,最后就能获得casecode啦!
数据解析
这里有两种思路,一种是直接在最后的小页中提取出全部信息,除此之外呢,在上一步获得casecode的过程中我们会发现相应的课程代码会同时携带着年级,学科等信息,
只需要在小页中解析剩余数据就可,博主这里是采用的第二种。
对于页面解析,这里直接xpath定位就可,而视频链接与图片链接建议采用正则表达式。
在实际需求中学姐向我说明,在挑选课程中有一步筛选,要求在每一本教材中,如果封面全都是
,也就是没有授课老师在封面中,则需要我们跳过这个小章节,只获取有老师的章节,但如果一本书中全部都是没有老师的章节,那就不管三七二十一直接获取所有章节内容。
所以这里需要我们进行一步逻辑判断。
代码实现
from lxml import etree
import openpyxl
import re
import requests
headers={'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36 SLBrowser/7.0.0.4071 SLBChan/30'}
lis=['....']#博主这里就不把list搬过来了,大家自行获取
wb = openpyxl.load_workbook('源.xlsx')
cout=1
for t in lis:
njname= t['njName']
if '下' in njname:
flag=True
else:
flag=False
for i in t['subjectsList']:
xk=['道德与法治','音乐','美术','科学','北师大']
flag1=True
Count=1
xkname=i['xkName']
for m in xk:
if m in xkname:
flag1=False
if flag1==False:
continue
sheet = wb.get_sheet_by_name(njname+'('+xkname+')')
#sheet.append(['ID','年级','学科','章节','课节名称','主讲人','主讲人简介','指导教师','指导教师简介','M3U8视频地址','视频第一帧默认图片','课节视频网页地址'])
print("开始 ",njname,' ',xkname)
for j in i['danYuanList']:
danyuanname=j['danyuanName']
for x in j['caseList']:
try:
code=x['caseCode']
data=[str(Count)]
url='https://tongbu.eduyun.cn/tbkt/tbkthtml/wk/weike/2020'+code[4]+'J/'+code+'.html'
page=str(requests.get(url=url,headers=headers).content,'utf-8')
tree=etree.HTML(page)
if flag==True:
print('为下册')
ss=['一','二','三']
flag2=False
if '数学' in xkname:
flag2=True
elif "PEP"in xkname:
flag2=True
for s in ss:
if s in njname and '英语' in xkname:
flag2=True
if flag2==True:
print('特殊对象')
imglink=re.findall(r'image: "(https://.*?.jpg)"',page,re.S)
data.append(njname)
data.append(xkname)
data.append(danyuanname)
classname=tree.xpath('//div[@class="XiangX_T"]/h3/text()')[0]
vlink=re.findall(r'file: "(https://.*?.m3u8)"',page,re.M)
if len(re.findall(r'<h5>主讲人:(.*?)</h5>',page,re.M))==0:
data.append(classname)
data.append(' ')
data.append(' ')
data.append(' ')
data.append(' ')
data.append(vlink[0])
data.append(imglink[0])
data.append(url)
elif len(re.findall(r'<h5>主讲人:(.*?)</h5>',page,re.M))==1:
mainman=re.findall(r'<h5>主讲人:(.*?)</h5>',page,re.M)[0]
text_mainman=re.findall(r'<p class="GuGan GuGan1">简介:(.*?)</p>',page,re.M)[0]
if len(re.findall(r'<h5>指导教师:(.*?)</h5>',page,re.M))==0:
data.append(classname)
data.append(mainman)
data.append(text_mainman)
data.append(' ')
data.append(' ')
data.append(vlink[0])
data.append(imglink[0])
data.append(url)
elif len(re.findall(r'<h5>指导教师:(.*?)</h5>',page,re.M))==1:
helper=re.findall(r'<h5>指导教师:(.*?)</h5>',page,re.M)[0]
text_helper=re.findall(r'<p class="GuGan GuGan1">简介:(.*?)</p>',page,re.M)[1]
data.append(classname)
data.append(mainman)
data.append(text_mainman)
data.append(helper)
data.append(text_helper)
data.append(vlink[0])
data.append(imglink[0])
data.append(url)
sheet.append(data)
print('round ',cout,' over!')
#print(data)
cout+=1
Count+=1
else:
print('非特殊对象')
tar=tree.xpath('//h4[@class="XiaZi"]')
if tar==[]:
print('[][[[[[[[[]]]]]]]]')
imglink=re.findall(r'image: "(https://.*?.jpg)"',page,re.S)
data.append(njname)
data.append(xkname)
data.append(danyuanname)
classname=tree.xpath('//div[@class="XiangX_T"]/h3/text()')[0]
vlink=re.findall(r'file: "(https://.*?.m3u8)"',page,re.M)
if len(re.findall(r'<h5>主讲人:(.*?)</h5>',page,re.M))==0:
data.append(classname)
data.append(' ')
data.append(' ')
data.append(' ')
data.append(' ')
data.append(vlink[0])
data.append(imglink[0])
data.append(url)
print('data=',data)
elif len(re.findall(r'<h5>主讲人:(.*?)</h5>',page,re.M))==1:
mainman=re.findall(r'<h5>主讲人:(.*?)</h5>',page,re.M)[0]
text_mainman=re.findall(r'<p class="GuGan GuGan1">简介:(.*?)</p>',page,re.M)[0]
if len(re.findall(r'<h5>指导教师:(.*?)</h5>',page,re.M))==0:
data.append(classname)
data.append(mainman)
data.append(text_mainman)
data.append(' ')
data.append(' ')
data.append(vlink[0])
data.append(imglink[0])
data.append(url)
print('data=',data)
elif len(re.findall(r'<h5>指导教师:(.*?)</h5>',page,re.M))==1:
helper=re.findall(r'<h5>指导教师:(.*?)</h5>',page,re.M)[0]
text_helper=re.findall(r'<p class="GuGan GuGan1">简介:(.*?)</p>',page,re.M)[1]
data.append(classname)
data.append(mainman)
data.append(text_mainman)
data.append(helper)
data.append(text_helper)
data.append(vlink[0])
data.append(imglink[0])
data.append(url)
print('data=',data)
sheet.append(data)
print('round ',cout,' over!')
#print(data)
cout+=1
Count+=1
else:
print('!!!!!!!!!!!!!!!!!!!!!!!')
pass
elif flag==False:
print('为上册')
imglink=re.findall(r'image: "(https://.*?.jpg)"',page,re.S)
data.append(njname)
data.append(xkname)
data.append(danyuanname)
classname=tree.xpath('//div[@class="XiangX_T"]/h3/text()')[0]
vlink=re.findall(r'file: "(https://.*?.m3u8)"',page,re.M)
if len(re.findall(r'<h5>主讲人:(.*?)</h5>',page,re.M))==0:
data.append(classname)
data.append(' ')
data.append(' ')
data.append(' ')
data.append(' ')
data.append(vlink[0])
data.append(imglink[0])
data.append(url)
elif len(re.findall(r'<h5>主讲人:(.*?)</h5>',page,re.M))==1:
mainman=re.findall(r'<h5>主讲人:(.*?)</h5>',page,re.M)[0]
text_mainman=re.findall(r'<p class="GuGan GuGan1">简介:(.*?)</p>',page,re.M)[0]
if len(re.findall(r'<h5>指导教师:(.*?)</h5>',page,re.M))==0:
data.append(classname)
data.append(mainman)
data.append(text_mainman)
data.append(' ')
data.append(' ')
data.append(vlink[0])
data.append(imglink[0])
data.append(url)
elif len(re.findall(r'<h5>指导教师:(.*?)</h5>',page,re.M))==1:
helper=re.findall(r'<h5>指导教师:(.*?)</h5>',page,re.M)[0]
text_helper=re.findall(r'<p class="GuGan GuGan1">简介:(.*?)</p>',page,re.M)[1]
data.append(classname)
data.append(mainman)
data.append(text_mainman)
data.append(helper)
data.append(text_helper)
data.append(vlink[0])
data.append(imglink[0])
data.append(url)
sheet.append(data)
print('round ',cout,' over!')
#print(data)
cout+=1
Count+=1
except:
cout+=1
print(cout,' 失败!!!')
print(url)
print(cout,'条')
wb.save("Data.xlsx")
对文章内容有问题请邮箱联系 sangyunchang1@163.com
一定会尽力回复