分析一下他们的代码,我在浏览器中对应位置右键,然后点击检查元素,可以找到对应部分的代码。但是,直接查看当前网页的源码发现,里面并没有对应的代码。我猜测这里是根据服务器上的数据动态生成的这部分代码,所以我们需要找到数据文件,以便向服务器申请,得到这部分资源。
在刚才查看元素的地方接着找数据文件,在Network里面的文件中很顺利的就找到了,并在报文中拿到了URL和请求方法。
查看一下这个文件发现是JSON文件,那样的话难度就又降低了,因为Python中有json库,解析json的能力很强。可以直接将json转换为字典和列表类型。
在这里我简单介绍一下数据解析的过程吧。首先,我将爬取到的json文本转换成某种数据类型,具体由数据决定,一般不是字典就是列表。查看类型发现是字典,且字典中有三个key值,而我们需要的key在一个叫data的key中。
而data中的数据是一个学生信息的列表类型,列表的每个元素都是一个字典,包括学生姓名,学号等信息。可以利用下标获取列表元素,并用key值得到你想拿到的信息。比如,利用Url得到网页链接。
这时候我们爬取需要的信息的准备工作可以说是结束了,我们拿到了数据的URL,并且知道了数据类型和数据结构。于是,我们只需要用requests库爬一下这个页面,然后用json解析一下,并且筛选有用的信息就好了。
(没用到BeautifulSoup和re库有点小失落)
接下来就是创建文件,就没有什么难度了。只是在为每个学生创建文件的时候注意一下,创建好以后及时的回到上层目录,否则,可能会让文件一层层的嵌套下去。
代码
#-*- coding:utf-8 -*-
importrequestsimportjsonimportos#抓取页面
url = 'https://edu.cnblogs.com/Homework/GetAnswers?homeworkId=2420&_=1542959851766'
try:
r= requests.get(url,timeout=20)
r.raise_for_status()
r.encoding=r.apparent_encodingexcept:print('网络异常或页面未找到,请重试')#利用json拿到数据列表,每个列表元素都是字典
datas = json.loads(r.text)['data']
result= ""
#数据处理
for data indatas:
result+= str(data['StudentNo'])+','+data['RealName']+','+data['DateAdded'].replace('T',' ')+','+data['Title']+','+data['Url']+'\n'
#写入文件
with open('hwlist.csv','w') as f:
f.write(result)#创建文件夹hwFolder
os.mkdir('hwFolder')
os.chdir('hwFolder')#创建每个学生的作业文件
for data indatas:#创建目录
os.mkdir(str(data['StudentNo']))
os.chdir(str(data['StudentNo']))#抓取页面
try:
webmsg= requests.get(data['Url'],timeout=20)
webmsg.raise_for_status()
webmsg.encoding=webmsg.apparent_encodingexcept:print('网络异常或页面未找到,请重试')#保存抓到的页面
with open(str(data['StudentNo'])+'.html','wb') as f:
f.write(webmsg.content)
os.chdir(os.path.pardir)
部分结果展示
上图是hwlist.csv文件的部分结果(Excel下打开)
玩个稍复杂点的
像之前那样爬取页面的话,其实是有点问题的。首先,我们只是爬取了页面的内容,但是并没有抓取到页面的样式,页面显示会不太正常,排版混乱。其次,页面中还有图片等元素都不会显示出来。而且,如果遇到网络问题代码需要再次运行的时候还会遇到一个问题,那就是目录已经存在了,我们在创建目录就会失败。除此之外还是有不少问题的,此处我先解决之前说到的几个问题。即显示问题和目录问题。
如何解决我提到的这些问题呢,目录问题我使用了一种比较容易实现的方案,那就是先判断当前目录是否存在,如果不存在就创建目录,否则就什么都不做。至于文件,暂定的方法是直接覆盖。显示问题也比较好解决,抓取网页和抓取样式或者网页其实都一样,就是用URL发送一个请求,来获得这个资源,其实和抓取HTML相比,就是文件格式不太一致。
以抓取样式表(CSS)为例,样式的URL怎么获取呢?有一些样式是在一个叫做Link的标签的href属性里,这里面就是外联样式存储的位置。把它提取出来,请求这个样式,并且修改原来的href属性为抓到的文件在自己电脑上的保存位置即可。这样的话即可保证抓到的CSS可以正常使用,确保排版正确。
当然了,即使这样,和原本的网页也是有差别的,因为抓取到的资源还是不够,和浏览器中获得的元素对比一下就会发现还差不少。鉴于本人能力有限,这里就补充一下爬取外联CSS和图片的内容,感兴趣的可以看一看。
Tips:这里解析HTML页面借助了强大的BeautifulSoup4库(解析标签和玩一样)和re库,使工作量减少了不少。(安装bs4库: pip install BeautifulSoup4)
#-*- coding:utf-8 -*-
importrequestsimportjsonimportosimportrefrom bs4 importBeautifulSoupdef getHtml(url,timeout=110):try:
res=requests.get(url,timeout)
res.raise_for_status()
res.encoding=res.apparent_encodingreturnresexcept:print('网络异常,'+url+"爬取失败")def saveFile(name,content,mode='w'):try:
with open(name,mode) as f:
f.write(content)except:print("文件"+name+"创建失败")defgetSource(text):#抓取样式
root_url = 'https://www.cnblogs.com'soup= BeautifulSoup(text,'html.parser')for i in soup('link'):
css_list= [css for css in i['href'].split('/') if 'css' incss]if css_list!=[]:
filename= re.search(r'.*css',css_list[0]).group(0)
r= requests.get(root_url+i['href'])
saveFile(filename,r.content,'wb')
text= text.replace(i['href'],'Source/'+filename)#抓取图片 用户自己插入的图片和网站自己生成的图片都抓
#用户自己插的那些格式很乱……用户自己搞的东西就是个坑
for i in soup('img'):try:
img_list= [img for img in i['src'].split('/') if 'gif' in img or 'png' in img or 'jpeg' inimg]except KeyError :#某用户自己改了HTML代码 得让我单独判断一下
img_list =[]if img_list!=[]:
filename=img_list[0]try:
r= requests.get(root_url+i['src'])
r.raise_for_status()except:if not 'http' in i['src']:
r= requests.get("https:"+i['src'])else:#又是某用户写博客用了HTML编辑器,写的还不对
r = requests.get(i['src'])
saveFile(filename,r.content,'wb')
text= text.replace(i['src'],'Source/'+filename)#text用于修改原始的页面链接,保证本地可以正常查看页面
returntext#############################主程序#############################抓取页面 并得到数据
r = getHtml('https://edu.cnblogs.com/Homework/GetAnswers?homeworkId=2420&_=1542959851766')
datas= json.loads(r.text)['data']#处理数据并将数据写入文件
result = ""
for data indatas:
result+= str(data['StudentNo'])+','+data['RealName']+','+data['DateAdded'].replace('T',' ')+','+data['Title']+','+data['Url']+'\n'saveFile('hwlist.csv',result,'w')#创建文件夹hwFolder
if not os.path.exists('hwFolder'):
os.mkdir('hwFolder')
os.chdir('hwFolder')#创建每个学生的作业文件
for data indatas:#创建目录
if not os.path.exists(str(data['StudentNo'])):
os.mkdir(str(data['StudentNo']))
os.chdir(str(data['StudentNo']))#抓取页面
webmsg = requests.get(data['Url'])print('当前的URL:'+data['Url'])#等待的过程有字出来不会无聊
#页面的一些资源
if not os.path.exists('Source'):
os.mkdir('Source')
os.chdir('Source')
webtext=getSource(webmsg.text)
os.chdir(os.path.pardir)
saveFile(str(data['StudentNo'])+'.html',webtext.encode(),'wb')
os.chdir(os.path.pardir)
如果你的网络没问题,讲道理,应该不会抛异常。接下来找个页面看看效果吧:
排版抓出来了,挺炫的,当然,图片也抓了。
考虑到有人会HTML,我把被程序调整后的HTML代码找一个给大家看看,箭头指向的地方都是程序自己改过的地方:
其实,虽然现在又和原页面接近了不少,但是……我暂时没有时间继续完善了,以后还会继续完善。给大家一个原博客的图片,你会我先我还是少了些东西。暂时先这样吧。