查看原文
其他

完了,小林网站的图片都挂了

小林coding 小林coding 2023-02-06

作者:小林coding

图解网站:https://xiaolincoding.com/

大家好,我是小林。

最近几天收到好几位读者私信说,我的网站有些文章的图片加载不出来,是不是被攻击了?

倒不是这个原因,是因为我用的图床在国内凉了。

我的图床方案是 Github + jsDelivr CDN,这套不花一毛钱的方案,一用就用了好几年了。

羊毛总就会被薅完的一天。在去年 12 月 jsDelivr 就出问题了,jsDelivr 域名备案被吊销,导致国内 CDN 提供商网宿移除了 jsDelivr 的账号,然后访问的速度越来越慢。

现在测速 jsDelivr CDN,访问延时基本都是好几千毫秒,这感人速度,感谢大家没把图解网站拉黑

五一节也来了,假期里肯定有不少人也会卷起来,更换图床地址这件事迫在眉头,所以自己掏钱买了 OSS 存储服务器。

可是,我网站的图片有 1000 多张啊!不可能手动一个一个去替换每一张图片的图床地址吧,这太不符合程序员的做法了。

这种繁琐的事情,肯定得要用程序来解决。所以,后面我想了一个快速替换图床地址的方案:

  • 先把所有图片下载下来,并且要按 URL 目录结构保存图片;
  • 然后以目录的方式上传所有图片到某云厂商 OSS 对象服务;
  • 最后把所有文章的图床地址的域名替换到新图床地址的域名;

这个替换方案保持了原本图片地址的 URL 层级结构,所以只需要替换图片地址的域名就可以了。

接下来,给大家实战一把。

下载图片

过滤图片地址到文件

首先,需要把所有文章用了 cdn.jsdelivr.net  的图片地址给过滤到文件。

进入文章目录后,通过下面这个命令递归找出所有文章的图片地址。

grep -r "cdn.jsdelivr.net" ./*

通过下面这个命令,可以看到总共有 839 处地方用了 jsdelivr 图床地址。

[root@xiaolin docs]# grep -r "cdn.jsdelivr.net" ./ | wc -l
839

但是这样过滤还不够,得把图片地址单独过滤出来,于是我通过下面这个命令,把(地址)字符串中的地址 给过滤出来。

grep -r "cdn.jsdelivr.net" ./* | cut -d '(' -f2 | cut -d ')' -f1

然后把过滤出来的图片地址保存到一个 list.txt 文件中。

grep -r "cdn.jsdelivr.net" ./* | cut -d '(' -f2 | cut -d ')' -f1 > list.txt

编写 Python 程序

过滤出所有文章的图片地址后,就可以写一个 Python 程序,遍历 list.txt 文件中的图片地址,然后将图片下载下来,并按照 URL 的目录结构保存图片文件。

我在网上找了个下载网站文件 Python 程序,然后在此基础上改了一点。

import urllib.request
import requests
import re, os
from urllib.parse import quote
import ssl


ssl._create_default_https_context = ssl._create_unverified_context

def get_file(url):
    '''
    递归下载网站的文件
    :param url:
    :return:
    '''


    if isFile(url):
        try:
            download(url)
        except Exception as e:
            print(url)
            print("download failed : " + str(e))
            pass
    else:
        urls = get_url(url)
        for u in urls:
            get_file(u)

def isFile(url):
    '''
    判断一个链接是否是文件
    :param url:
    :return:
    '''

    if url.endswith('/'):
        return False
    else:
        return True

def download(url):
    '''
    :param url:文件链接
    :return: 下载文件,自动创建目录
    '''

    full_name = url.split('//')[-1]
    url = quote(url, safe='/:?=@')
    filename = full_name.split('/')[-1]
    dirname = "/".join(full_name.split('/')[:-1])
    if os.path.exists(dirname):
        pass
    else:
        os.makedirs(dirname, exist_ok=True)
    print(url)
    urllib.request.urlretrieve(url, full_name)

def get_url(base_url):
    '''
    :param base_url:给定一个网址
    :return: 获取给定网址中的所有链接
    '''

    text = ''
    try:
        text = requests.get(quote(base_url, safe='/:?=@')).text
    except Exception as e:
        print("error - > ",base_url,e)
        pass
    reg = '<a href="(.*)">.*</a>'
    urls = [base_url + url for url in re.findall(reg, text) if url != '../']
    return urls

if __name__ == '__main__':
    '''
    遍历list.txt文件中的 URL,并下载
    '''

    with open('list.txt''r'as f:
        lines = f.readlines()
        url_list = []
        for line in lines:
            get_file(line.strip('\n'))

执行完 Python 程序后,图片都按 URL 目录结构保存起来了。

上传图片

下载完图片后,直接把图片目录上次到某云厂商 OSS 对象存储服务。

上传完成,可以看到新图片地址的 URL 目录结构还是与原本图片地址的  URL 目录结构是一样的。

所以,最后的工作就是把全部文章里的图片地址中的域名从 cdn.jsdelivr.net 替换成 xiaolincoding.oss-cn-shenzhen.aliyuncs.com

替换图床地址

替换文件里的字符串,我们可以使用 sed 命令。举个例子,假设 a.txt 文件内容如下:

https://cdn.jsdelivr.net/abc/1.jpg

然后我们可以使用下面这条命令替换图片域名地址:

sed  -i 's/cdn.jsdelivr.net/xiaolincoding.oss-cn-shenzhen.aliyuncs.com/g'  a.txt

注意这条 sed 命令是加了 -i 参数,是直接修改文件内容的,所以最好修改文件前,先去掉  -i 参数,测试下输出的结果是否是你预期的。

我写了一个简单 Shell 脚本,把所有文章中的图片域名地址替换掉。

#!/bin/bash

for file in `find /home/vuepress_xiaolincoding/docs/ -name "*.md"`
do
    echo $file
    sed -i 's/cdn.jsdelivr.net/xiaolincoding.oss-cn-shenzhen.aliyuncs.com/g' $file
done

执行完这个 Shell 脚本后,替换图床地址的工作就全部完成了!

最后,测试一下访问图片的速度,访问速度从几千毫秒下降至 100 毫秒了。

忘记充钱

网站的图床在昨晚就迁移完了,然后早上有读者说,网站的图片都挂了。

然后看手机短信,原来是我没有充钱。。。。。

好了,钱冲进去了,现在网站图片的访问不再是问题了!

哦对,五一节了,大家不要偷偷自己卷,要卷一起卷

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存