用Python自动下载网站所有文件
作者:somenzz 发布时间:2021-02-09 18:57:35
目录
总体思路:
判断链接是否指向文件:
下载文件:
获取 url 下的所有链接:
最近维基 jie mi 彻底公开了网站的全部文件,我就在想如何使用 Python 将其下载到本地永久保存,于是就有了这篇文章,写爬虫会遇到很多坑,借鉴他人经验,考虑越全面,出错的概率就越小。
假如一个网站,里面有很多链接,有指向文件的,有指向新链接的,新的链接点击进去后,仍然是有指向文件的,有指向新链接的,类似一个文件夹,里面即有文件,又有目录,目录中又有文件和目录。如何从这样的网站上下载所有的文件,并按网站的目录结构来保存这些文件呢?
关键词:Python、下载、正则表达式、递归。
按照自顶向下来设计程序,我们整理自己的思路,然后使用 Python 语言来翻译下即可。
思路:由于目录的深度不固定,也不可能穷举,且每一个目录的处理方式和子目录父目录的处理流程都是一样的,因此我们可以使用递归来下载所有文件。
递归代码必须要有退出条件,退出条件要放在前面,本例中的递归退出条件就是:如果是文件就下载,下载完递归函数即完成任务。
总体思路:
1、给定一个 url,判断是否是文件,如果是文件,下载即可,然后函数结束。
2、如果给定 url 不是文件,那么访问该 url,并获取它下面的所有链接。
3、遍历步骤 2 产生的所有链接,递归的执行步骤 1 和 2,直到程序运行结束。
以上思路,用代码描述如下:
import urllib.request
import requests
import re, os
def get_file(url):
'''
递归下载网站的文件
:param url:
:return:
'''
if isFile(url):
print(url)
try:
download(url)
except:
pass
else:
urls = get_url(url)
for u in urls:
get_file(u)
前面导入的包在接下来函数中会用到,下面就是逐渐层向下,实现子功能。
判断链接是否指向文件:
这里总结 url 规律,很容易写出。
def isFile(url):
'''
判断一个链接是否是文件
:param url:
:return:
'''
if url.endswith('/'):
return False
else:
return True
下载文件:
下载文件时要从 url 中获取文件应该存储的位置,并使用 os.makedirs 来创建多级目录。然后使用 urllib.request.urlretrieve 来下载文件。
def download(url):
'''
:param url:文件链接
:return: 下载文件,自动创建目录
'''
full_name = url.split('//')[-1]
filename = full_name.split('/')[-1]
dirname = "/".join(full_name.split('/')[:-1])
if os.path.exists(dirname):
pass
else:
os.makedirs(dirname, exist_ok=True)
urllib.request.urlretrieve(url, full_name)
获取 url 下的所有链接:
这里要具体网站具体分析,看看如何使用正则表达式获取网页中的链接,这样的正则表达式可以说是再简单不过了。
def get_url(base_url):
'''
:param base_url:给定一个网址
:return: 获取给定网址中的所有链接
'''
text = ''
try:
text = requests.get(base_url).text
except Exception as e:
print("error - > ",base_url,e)
pass
reg = '<a href="(.*)" rel="external nofollow" >.*</a>'
urls = [base_url + url for url in re.findall(reg, text) if url != '../']
return urls
这里有个小坑,就是网站有个链接是返回上级页面的,url 的后辍是 '../' 这样的链接要去掉,否则递归函数就限入了死循环。
接下来就是写主函数,执行任务了,慢慢等它下载完吧。
if __name__ == '__main__':
get_file('https://file.wikileaks.org/file/')
其实,还会存两个问题:
1、假如网站某页有个链接它指向了首页,那么递归程序仍然会限入一个死循环,解决方法就是将访问过的 url 保存在一个列表里(或者其他数据结构),如果接下来要访问的 url 不在此列表中,那么就访问,否则就忽略。
2、如果下载的过程中程序突然报错退出了,由于下载文件较慢,为了节约时间,那么如何让程序从报错处继续运行呢?这里可采用分层递归,一开始时先获取网站的所有一级 url 链接,顺序遍历这些一级 url 链接,执行上述的 get_file(url) ,每访问一次一级 url 就将其索引位置加1(索引位置默认为0,存储在文件中或数据库中),程序中断后再运行时先读取索引,然后从索引处开始执行即可。另外,每下载成功一个文件,就把对应的 url 也保存在文件中或数据库中,如果一级 url 下的链接已经下载过文件,那么就不需要重新下载了。
来源:https://cloud.tencent.com/developer/article/1752052
猜你喜欢
- <%'============================================================
- 随着ajax再网站建设中的的大范围流行,XmlHttp也自然被人们所熟悉。本文介绍了asp任何检测服务器端是否支持xmlhttp组件的方法,
- 网页过渡是指当浏览者进入或离开网页时,页面呈现的不同的刷新效果,比如卷动、百叶窗等。注:通过模板所建网页无法添加网页过渡效果!制作步骤:1、
- 本文实例讲述了Python实现矩阵加法和乘法的方法。分享给大家供大家参考,具体如下:本来以为python的矩阵用list表示出来应该很简单可
- 今天交流会上,分享前端的开发经验,有一条虽然很快带过,但是我倒是印象蛮深刻的,就写点小结来分享一下吧。不知道是标准害了大家还是大家害了标准,
- 解决Microsoft VBScript 运行时错误 (0x800A0046) 没有权限的解决方案,0x800a0046错误。前段时间在做站
- 今天想说的是内容和容器的关系,顺便把之前设计中碰到的问题和大家一起探讨下。我们从软件的设置说起。(这里以QQ的设置举例)一个软件的设置(常称
- 在产品开发中,由UED发起的项目越来越多,但是现在的问题是很难为其设定商业价值的目标。如果没有明确的商业价值目标,很多公司根本没办法花大成本
- 在做一个在线交流的网站时,有个问题很令我头疼,就是关于实时统计在线用户的问题,客户要求:统计当前在线人数、游客人数、会员人数、在线用户列表,
- 看代码吧~package mainimport ("fmt""io""net/http&q
- 在一行内声明CSS,对比下面两个:h2 {font-size:18px; border:1px solid&n
- 内置方法 说明 __init__(self,...) 初始化对象,在创建新对象时调用 __del__(self) 释放对
- 在SQL Server中,提供了通过Exchange或Outlook收发邮件的扩展存储过程。下面简单地介绍一下:一、启动SQL Mail:x
- 我们经常会遇到多重查询问题,而长长的SQL语句往往让人丈二和尚摸不着头脑。特别是客户端部分填入查询条件时,如用普通方法将更是难上加难。以下巧
- 问题引入什么时候选择 T 作为参数类型,什么时候选择 *T 作为参数类型?[ ] T 是传递的指针还是值?选择 [ ] T 还是 [ ] *
- 设置cookie每个cookie都是一个名/值对,可以把下面这样一个字符串赋值给document.cookie:document.cooki
- apache对php的支持是通过apache的mod_php5模块来支持的,这点与nginx不同。nginx是通过第三方的fastcgi处理
- MaxDB是MySQL AB公司通过SAP认证的数据库。MaxDB数据库服务器补充了MySQL AB产品系列。某些MaxDB特性在MySQL
- jQuery由美国人John Resig创建,至今已吸引了来自世界各地的众多javascript高手加入其team,包括来自德国的J&
- 本文实例讲述了PHP实现的DES加密解密类定义与用法。分享给大家供大家参考,具体如下:今天写App接口的时候需要传递加密数据给APP端,于是