├── .gitignore
├── .idea
├── .gitignore
├── blog_img_script.iml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── misc.xml
└── modules.xml
├── README.md
├── change_address.py
└── collection.py
/.gitignore:
--------------------------------------------------------------------------------
1 | imgs/
2 | /.idea/
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 | # Datasource local storage ignored files
5 | /../../../../:\pythonProjects\blog_img_script\.idea/dataSources/
6 | /dataSources.local.xml
7 | # Editor-based HTTP Client requests
8 | /httpRequests/
9 |
--------------------------------------------------------------------------------
/.idea/blog_img_script.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
12 |
13 |
14 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 批量博客防盗链接图片站点转移脚本
2 | 最近CSDN开始对图片施加防盗链接了。
3 | 我个人经常在CSDN上进行写作,前一段时间我选择自己建站,为了省事,我直接使用了CSDN上的图片地址,当你在CSDN上写作时你上传的图片会存储在CSDN的服务器中,
4 | 可以直接在网页上输入URL访问。但是最近CSDN对图片施加了防盗链接,我个人网站上的所有图片全都看不到了。
5 | 搜索了一些解决方案,大多都治标不治本。于是我选择将图片上传至自己的服务器,通过Nginx进行代理。这个脚本适合与和我情况类似的朋友们使用:
6 | 1.个站图片被防盗链接限制 2.有云服务器
7 | ## 脚本使用方法
8 | 1. 克隆仓库并进入项目目录
9 | ```
10 | git clone https://github.com/Stephen-SMJ/BlogImageTransfer.git
11 | cd blog_img_script
12 | ```
13 | 2. 执行图片下载脚本(folder_path为你本地的md文件存储路径,如果本地没存要先去网站上下载到本地)
14 | ```
15 | python collection.py --folder_path "the output path of your download images" --output_path ./imgs/
16 | ```
17 | 
18 | 3. 此时你博客文件夹中的所有图片都被下载到了--output_path 这个目录,你需要把这个文件夹上传至你的服务器,并配置Nginx映射
19 | 4. 修改所有md文件中的图片路径(只更域名,会自动保留原图片名称以及描述)
20 | ```
21 | python change_address.py --folder_path "the address of your md file in your blog project " --server_address "nginx中配置好的图片url"
22 | ```
23 | 
24 |
25 | 完成,此时再访问你自己的博客网站应该就可以正常显示图片了!
26 | **如果觉得好用麻烦高抬贵手点点star!**
--------------------------------------------------------------------------------
/change_address.py:
--------------------------------------------------------------------------------
1 | import os
2 | import re
3 | import argparse
4 |
5 | parser = argparse.ArgumentParser()
6 | parser.add_argument('--folder_path', type=str, help='the path of your blog fold')
7 | parser.add_argument('--server_address', type=str, help='the address of your server')
8 | arg = parser.parse_args()
9 |
10 | # 输入文件夹路径和输出路径
11 | folder_path = arg.folder_path
12 | server_url = arg.server_address #指定图片的服务器URL
13 |
14 | # 定义正则表达式匹配图片URL
15 | pattern = re.compile(r"\!\[(.*?)\]\((.*?)\)")
16 |
17 |
18 | # 使用正则表达式替换图片URL
19 | def replace_url(match):
20 | title = match.group(1) #![图片的title]
21 | image_path = match.group(2) #(图片的url)
22 | image_name = os.path.basename(image_path)
23 | new_url = f"{server_url}{image_name}"
24 | return f""
25 |
26 | # 遍历指定文件夹下的所有md文件
27 | for file_name in os.listdir(folder_path):
28 | if file_name.endswith(".md"):
29 | file_path = os.path.join(folder_path, file_name)
30 | with open(file_path, "r+", encoding="utf-8") as file:
31 | content = file.read()
32 | try:
33 | new_content = re.sub(pattern, replace_url, content) #第二个参数可以是一个函数,这个函数的第一个参数就是当前匹配到的子字符串的对象(即MatchObject)
34 | file.seek(0) #使用seek可以一次读写,不用再打开一遍文件写入, seek(0)指针回到开头
35 | file.truncate() #清空文件内容
36 | file.write(new_content)
37 | print("fished transfer url in {}".format(file_name))
38 | file.close()
39 | except:
40 | print("{} occurs a error".format(file_name))
41 |
42 |
43 | # !: 匹配以感叹号开头的字符串,即图片链接的标记符号。
44 | # \[和\]: 匹配中括号中的任意字符,即图片的标题。这里使用\[和\]进行转义。
45 | # .*?: 匹配中间的任意字符,即图片的描述信息。这里使用.*?表示非贪婪模式,避免匹配到多个图片链接。
46 | # \(和\): 匹配括号中的任意字符,即图片的链接地址。这里同样使用\(和\)进行转义
47 | # ()将链接地址提取出来作为一个group。 group(1) 列出第一个括号匹配部分,group(2) 列出第二个括号匹配部分
--------------------------------------------------------------------------------
/collection.py:
--------------------------------------------------------------------------------
1 | import os
2 | import re
3 | import urllib.request
4 | import argparse
5 |
6 | parser = argparse.ArgumentParser()
7 | parser.add_argument('--folder_path', type=str, help='the path of your blog fold')
8 | parser.add_argument('--output_path', type=str, help='the output path of your download images')
9 | arg = parser.parse_args()
10 |
11 | folder_path = arg.folder_path
12 | output_path = arg.output_path
13 |
14 | # 遍历文件夹下的所有md文件
15 | for filename in os.listdir(folder_path):
16 | if filename.endswith(".md"):
17 | with open(os.path.join(folder_path, filename), "r", encoding="utf-8") as file:
18 | content = file.read()
19 | # 使用正则表达式提取图片链接
20 | img_urls = re.findall("!\[.*?\]\((.*?)\)", content)
21 | # 下载图片
22 | for url in img_urls:
23 | try:
24 | img_name = os.path.basename(url)
25 | img_path = os.path.join(output_path, img_name)
26 | urllib.request.urlretrieve(url, img_path)
27 | print(f"Downloaded {img_name} from {url}")
28 | except:
29 | print(f"Error: Downloaded {url} failed !!!")
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------