python3 beautifulsoup 模块详解_023 python3 BeautifulSoup模块使用与Python爬虫爬取博客园作业...

分析一下他们的代码,我在浏览器中对应位置右键,然后点击检查元素,可以找到对应部分的代码。但是,直接查看当前网页的源码发现,里面并没有对应的代码。我猜测这里是根据服务器上的数据动态生成的这部分代码,所以我们需要找到数据文件,以便向服务器申请,得到这部分资源。

在刚才查看元素的地方接着找数据文件,在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代码找一个给大家看看,箭头指向的地方都是程序自己改过的地方:

其实,虽然现在又和原页面接近了不少,但是……我暂时没有时间继续完善了,以后还会继续完善。给大家一个原博客的图片,你会我先我还是少了些东西。暂时先这样吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值