使用MitmProxy离线缓存360度全景网页

举报
小小明-代码实体 发表于 2022/07/05 22:18:46 2022/07/05
【摘要】 📢博客主页:https://blog.csdn.net/as604049322 📢欢迎点赞 👍 收藏 ⭐留言 📝 欢迎讨论! 📢本文由 小小明-代码实体 原创,首发于 CSDN🙉...

📢博客主页:https://blog.csdn.net/as604049322

📢欢迎点赞 👍 收藏 ⭐留言 📝 欢迎讨论!

📢本文由 小小明-代码实体 原创,首发于 CSDN🙉

昨天遇到一个问题:

image-20220705085126329

有些涉及动态加载的网页,有游览器自带的保存网页功能是无法保存全部资源的。

假如我们手工挨个文件去保存,未免也太多了:

image-20220705085423728

超多的文件夹,一层一层的。

此时我为了实现离线缓存目标网页,想到了一个好方法,那就是通过支持python编程的代理,让每一个请求都根据URL保存对应的文件到本地。

MitmProxy的安装

比较推荐MitmProxy,安装方法在命令行中执行:

pip install mitmproxy

  
 
  • 1

MitmProxy分为mitmproxy,mitmdump和mitmweb三个命令,其中mitmdump支持使用指定的python脚本处理每个请求(使用-s参数指定)。

安装后我们需要安装证书MitmProxy对应的证书,访问:http://mitm.it/

直接访问会显示:If you can see this, traffic is not passing through mitmproxy.

这里我们先执行mitmweb启动一个网页版的代理服务器:

image-20220705093554905

我们给所使用的游览器,设置代理服务器的地址,以360安全游览器为例:

image-20220705093759680

在设置并使用MitmProxy提供的代理服务器之后再次访问http://mitm.it/就可以下载并安装证书了:

image-20220705094637765

下载后打开证书不断点击下一步即可安装完成。

此时访问百度,可以看到MitmProxy的证书验证信息:

image-20220705095101007

编写mitmdump所需的脚本

mitmdump所支持的脚本的模板代码如下:

# 所有发出的请求数据包都会被这个方法所处理
def request(flow):
    # 获取请求对象
    request = flow.request
    
# 所有服务器响应的数据包都会被这个方法处理
def response(flow):
    # 获取响应对象
    response = flow.response

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

request和response对象与requests库中的对象几乎一致。

我们的需求是根据url保存文件,只需要处理响应即可,先尝试缓存百度首页:

import os
import re

dest_url = "https://www.baidu.com/"


def response(flow):
    url = flow.request.url
    response = flow.response
    if response.status_code != 200 or not url.startswith(dest_url):
        return
    r_pos = url.rfind("?")
    url = url if r_pos == -1 else url[:r_pos]
    url = url if url[-1] != "/" else url+"index.html"
    path = re.sub("[/\\\\:\\*\\?\\<\\>\\|\"\s]", "_", dest_url.strip("htps:/"))
    file = path + "/" + url.replace(dest_url, "").strip("/")
    r_pos = file.rfind("/")
    if r_pos != -1:
        path, file_name = file[:r_pos], file[r_pos+1:]
    os.makedirs(path, exist_ok=True)

    with open(file, "wb") as f:
        f.write(response.content)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

将上述脚本保存为dump.py然后使用如下命令启动代理(先关闭之前启动的mitmweb):

>mitmdump -s dump.py
Loading script dump.py
Proxy server listening at http://*:8080

  
 
  • 1
  • 2
  • 3

刷新页面后已经顺利缓存了百度首页:

image-20220705103348348

使用python自带的服务器测试运行并访问一下:image-20220705103914089

可以看到已经顺利访问了本地的百度。

离线缓存360全景网页

将上述脚本的dest_url修改为如下地址并保存:

dest_url = "https://img360wcs.soufunimg.com/2022/03/25/gz/720/3943919a3a7b46769db6f2db1f4250e5/html"

  
 
  • 1

再次访问:https://img360wcs.soufunimg.com/2022/03/25/gz/720/3943919a3a7b46769db6f2db1f4250e5/html/index.html

如果发现保存的文件不够全,可以打开开发者工具,在网络选项卡勾选 禁用缓存 后,再次刷新网页:

image-20220705105213843

此时主体文件已经全部缓存:

image-20220705105256078

此时只要尽量多的在原始网页上游览各个方向,并放大缩小就可以尽量多缓存更多高清细节图片。

使用本地服务器启动测试已经顺利访问:

image-20220705110127236

不过原始脚本只缓存响应码为200的普通文件,上述网站还会返回响应码为206的分片音乐文件,如果也需要缓存就稍微复杂一些,下面我们研究一下如何缓存音乐文件。

缓存206分片文件

经过一番研究,将上述代码修改为如下形式即可:

import os
import re

dest_url = "https://img360wcs.soufunimg.com/2022/03/25/gz/720/3943919a3a7b46769db6f2db1f4250e5/html"


def response(flow):
    url = flow.request.url
    response = flow.response
    if response.status_code not in (200, 206) or not url.startswith(dest_url):
        return
    r_pos = url.rfind("?")
    url = url if r_pos == -1 else url[:r_pos]
    url = url if url[-1] != "/" else url+"index.html"
    path = re.sub("[/\\\\:\\*\\?\\<\\>\\|\"\s]", "_", dest_url.strip("htps:/"))
    file = path + "/" + url.replace(dest_url, "").strip("/")
    r_pos = file.rfind("/")
    if r_pos != -1:
        path, file_name = file[:r_pos], file[r_pos+1:]
    os.makedirs(path, exist_ok=True)

    if response.status_code == 206:
        s, e, length = map(int, re.fullmatch(
            r"bytes (\d+)-(\d+)/(\d+)", response.headers['Content-Range']).groups())
        if not os.path.exists(file):
            with open(file, "wb") as f:
                pass
        with open(file, "rb+") as f:
            f.seek(s)
            f.write(response.content)
    elif response.status_code == 200:
        with open(file, "wb") as f:
            f.write(response.content)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

保存修改完的脚本,mitmdump可以自动重载:

image-20220705120628591

清理缓存并重新访问之后,音乐文件已经顺利下载:

image-20220705120742615

总结

通过mitmdump我们已经顺利实现了对指定网站的缓存,以后想缓存其他网站到本地只需要修改dest_url的网址即可。

文章来源: xxmdmst.blog.csdn.net,作者:小小明-代码实体,版权归原作者所有,如需转载,请联系作者。

原文链接:xxmdmst.blog.csdn.net/article/details/125617140

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。