起因:

最近听电台看到了《矮大紧指北》,试听了一段之后觉得不错,但是试听过后要收费了,舍不得这钱啊。这时候就需要到网上找免费资源了。

于是找到了这个网页(暂且称为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,这叫学以致用。

希望能把这篇文章看完的你,也能在有一些灵感的时候,把自己曾经学过的东西给用上。