起因:
最近听电台看到了《矮大紧指北》,试听了一段之后觉得不错,但是试听过后要收费了,舍不得这钱啊。这时候就需要到网上找免费资源了。
于是找到了这个网页(暂且称为webA)共计136条,
这么多条url,点是不可能点的,这辈子都不可能点的
需求:
作为一个镇得了后台,撸得了前端,写得了脚本的优质程序员,这可不能忍,我需要扒下这个网站上所有的文件
分析:
这些url连接是城通网盘(暂且称为webB)
所以我需要获取url里面的信息,然后模拟普通下载的点击事件,普通下载的文件就是我所要下载的东西。
下载的文件是rar文件,解压密码在webA中有提到过
制定计划:
- 扒下所有url
- 实现普通下载
- 解压rar
过程:
- 解析webA,按下F12,找到这段代码
- 实现扒取数据,用js扒下所有的url以及标题,将a标签的内容复制下来。webA的访问页面比较长,所以没有直接从webA上面爬取,而是保存下来
- 解析webB,按下F12,定位到“普通下载”的按钮,可以看到onclick是free_down方法,根据js方法也是变量的特性,在控制台打印该方法,双击定位到该方法的位置,并将该js全部放到文本编辑器里并格式化代码,再定位到free_down方法,我这里使用的hbuilder。记录“普通下载”按钮里的入参,除去多余代码,得到如下截图,其实代码就是访问一个这样的url,然后获取返回json中的downurl字段,这个downurl就是下载的url了,于是得到一个用于获取下载连接的url,uid是全局变量,在控制台可以获得,file_id可以通过webB的地址url中获得,file_chk从“普通下载”按钮中通过字符串截取获取,rd使用一个通过js生成的固定的(所幸城通没有限制每次rd都必须不同)
- 实现下载,这里不需要太多文字,直接上代码
#!/usr/bin/python # -*- coding: UTF-8 -*- import downloadutil import os import requests from bs4 import BeautifulSoup """从webA中扒取的url及标题""" table={ "发刊词:高晓松指南,矮大紧指北":"https://u17096629.ctfile.com/fs/17096629-242578589" #以下135条直接省略 } for c in table: """拼接文件目录,使用相对路径""" path = "download/"+c + ".rar" """有可能因为网络问题需要多次重新运行,用作已下载判断""" if os.path.exists(path): print c + "已存在" continue url=table[c] """截取file_id""" file_id=url[url.rindex("-")+1:] """访问webB的url并解析""" response=requests.get(url) html=response.content soup = BeautifulSoup(html, 'html.parser') """查找出'普通下载'按钮,获取file_chk""" file_chk=soup.find_all('a', id='free_down_link')[0]["onclick"].split(",")[2].replace(" ",'').replace("'",'') """拼接获取下载url的api,并以json解析""" rarurl="https://u17096629.ctfile.com/get_file_url.php?uid=17096629&fid=" + file_id + "&folder_id=0&fid=" + file_id +\ "&file_chk=" + file_chk + "&mb=0&app=0&verifycode=&rd=0.26680044175096485" json=requests.get(rarurl).json() """容错判断,记录下那些出错了""" if str(json["code"])=='503': print "503:" + c continue """下载url中的数据""" downloadutil.file(json["downurl"],c + ".rar")
#!/usr/bin/python # -*- coding: UTF-8 -*- import requests import os import datetime """downloadutil.py""" def file(url,fileName): path = "download/"+fileName """对文件夹进行非空处理""" filedir = path[0:path.rindex("/")] if not os.path.exists(filedir): os.makedirs(filedir) print "开始下载" + fileName """开始下载文件""" res = requests.get(url) res.raise_for_status() with open(path, 'wb') as playFile: for chunk in res.iter_content(102400): print ".", playFile.write(chunk) print "\n尝试关闭" playFile.close() print "["+datetime.datetime.now().strftime("%H:%M:%S")+"]" + fileName + "下载成功"
5.解压
#!/usr/bin/python # -*- coding: utf8 -*- import rarfile import zipfile import os import re def un_rar(file_name,pwd=None): try: if file_name.split('.')[-1]=='rar': rar = rarfile.RarFile(file_name) rar.extractall(path=r'after',pwd=pwd) elif file_name.split('.')[-1]=='zip': zip = zipfile.ZipFile(file_name) zip.extractall(path=r'after',pwd=pwd) except Exception as e : print(e) print('Fail:'+file_name) else: print('Success') def point_file_name(path): return [os.path.join(item[0],file_name) for item in os.walk(path) for file_name in item[-1] if re.search(r'.rar$|.zip$',file_name)] if __name__ == '__main__': """压缩文件所在路径""" path = r'download' """解压密码""" pwd = 'vipziyuan' file_names = point_file_name(path) for file_name in file_names: un_rar(file_name,pwd=pwd)
结果:
就这样我把全集都下载下来了
小结:
爬虫不是一门技术,是一门应用。我从未学过爬虫的知识,但我知道爬虫的原理,作为一个web程序员我了解http协议,了解html,我顺带着还会一点python,这叫学以致用。
希望能把这篇文章看完的你,也能在有一些灵感的时候,把自己曾经学过的东西给用上。