起因:
最近听电台看到了《矮大紧指北》,试听了一段之后觉得不错,但是试听过后要收费了,舍不得这钱啊。这时候就需要到网上找免费资源了。
于是找到了这个网页(暂且称为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,这叫学以致用。
希望能把这篇文章看完的你,也能在有一些灵感的时候,把自己曾经学过的东西给用上。