《名侦探柯南》是一部长期连载的日本推理动画和漫画,围绕高中生侦探工藤新一化身为少年江户川柯南后,解决各种案件的故事。以下是《名侦探柯南》的主要版本分类:


1. TV版(动画剧集)

  • 首播:1996年1月8日,至今仍在连载。
  • 内容:以周播形式放送,根据漫画原作改编,并加入原创剧情(俗称“动画原创”)。
  • 集数:截至2025年1月,已超过1100集。
  • 特点:主要面向电视观众,剧情以单集案件和多集连续案件为主。

2. 剧场版(电影版)

  • 首映:1997年至今,每年一部剧场版。
  • 特点:以高质量的制作和独立的剧情为主,通常包含更多动作戏、悬疑和戏剧性,面向更广泛的观众群体。
  • 数量:截至2024年,已有27部剧场版。
  • 列表:1997-2024
    1. 1997年:《名侦探柯南:计时引爆摩天楼》(名探偵コナン 時計じかけの摩天楼)
    2. 1998年:《名侦探柯南:第十四个目标》(名探偵コナン 第14番目の標的)
    3. 1999年:《名侦探柯南:世纪末的魔术师》(名探偵コナン 世紀末の魔術師)
    4. 2000年:《名侦探柯南:瞳孔中的暗杀者》(名探偵コナン 瞳の中の暗殺者)
    5. 2001年:《名侦探柯南:通向天国的倒计时》(名探偵コナン 天国へのカウントダウン)
    6. 2002年:《名侦探柯南:贝克街的亡灵》(名探偵コナン ベイカー街の亡霊)
    7. 2003年:《名侦探柯南:迷宫的十字路口》(名探偵コナン 迷宮の十字路)
    8. 2004年:《名侦探柯南:银翼的奇术师》(名探偵コナン 銀翼の奇術師)
    9. 2005年:《名侦探柯南:水平线上的阴谋》(名探偵コナン 水平線上の陰謀)
    10. 2006年:《名侦探柯南:侦探们的镇魂歌》(名探偵コナン 探偵たちの鎮魂歌)
    11. 2007年:《名侦探柯南:绀碧之棺》(名探偵コナン 紺碧の棺)
    12. 2008年:《名侦探柯南:战栗的乐谱》(名探偵コナン 戦慄の楽譜)
    13. 2009年:《名侦探柯南:漆黑的追踪者》(名探偵コナン 漆黒の追跡者)
    14. 2010年:《名侦探柯南:天空的遇难船》(名探偵コナン 天空の難破船)
    15. 2011年:《名侦探柯南:沉默的15分钟》(名探偵コナン 沈黙の15分)
    16. 2012年:《名侦探柯南:第十一个前锋》(名探偵コナン 11人目のストライカー)
    17. 2013年:《名侦探柯南:绝海的侦探》(名探偵コナン 絶海の探偵)
    18. 2014年:《名侦探柯南:异次元的狙击手》(名探偵コナン 異次元の狙撃手)
    19. 2015年:《名侦探柯南:业火的向日葵》(名探偵コナン 業火の向日葵)
    20. 2016年:《名侦探柯南:纯黑的恶梦》(名探偵コナン 純黒の悪夢)
    21. 2017年:《名侦探柯南:唐红的恋歌》(名探偵コナン から紅の恋歌)
    22. 2018年:《名侦探柯南:零的执行人》(名探偵コナン ゼロの執行人)
    23. 2019年:《名侦探柯南:绀青之拳》(名探偵コナン 紺青の拳)4月
    24. 2019年:《名侦探柯南:绀青之拳(重映版)》(名探偵コナン 紺青の拳 再映)8月
    25. 2021年:《名侦探柯南:绯色的子弹》(名探偵コナン 緋色の弾丸)
    26. 2022年:《名侦探柯南:万圣节的新娘》(名探偵コナン ハロウィンの花嫁)
    27. 2023年: 《名侦探柯南:黑铁的鱼影》(名探偵コナン 黒鉄の魚影)
    28. 2024年:《名侦探柯南:百万美元的五稜星》(名探偵コナン 100万ドルの五稜星)

3. OVA版(Original Video Animation)

  • 数量:共12部,1999年至2012年发行。
  • 特点:通常为原创剧情,以附赠形式发布,例如随漫画特典或DVD发行。
  • 例子:
    • OVA1:《柯南 vs 基德 vs 阿剑 宝刀争夺大作战》
    • OVA10:《怪盗基德的惊异空中步行》

4. 特别篇

  • 类型:特殊长度的TV版(通常为1小时或以上),或在特殊节假日播出的特别内容。
  • 例子:
    • 《世纪末的福尔摩斯》
    • 《大阪双重迷案》

5. SP真人版(真人电视电影)

  • 数量:5部(2006-2011年)。
  • 特点:由真人演员出演,主要以工藤新一未变小前的故事为主。
  • 例子:
    • 《名侦探柯南:工藤新一的复活!与黑暗组织的对决》

6. 其他版本

  • 短片:如《迷你版柯南》,风格幽默轻松。
  • 衍生漫画和外传动画:
    • 《名侦探柯南:零的日常》(以安室透为主角的日常故事)
    • 《犯人犯泽先生》(搞笑风格,以黑影犯人为主角)

版本总结

  • TV版是主要剧情连载形式;
  • 剧场版每年一部,规模宏大;
  • OVA和特别篇多为补充故事;
  • 真人版和外传则是扩展内容。

文件信息

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
D:\software\mkvtoolnix>mkvinfo 难兄难弟-01.mkv
+ EBML 头
|+ EBML 版本: 1
|+ EBML 读取版本: 1
|+ EBML ID 最大长度: 4
|+ EBML 大小最大长度: 8
|+ 文档类型: matroska
|+ 文档类型版本: 4
|+ 文档类型读取版本: 2
+ 剪辑: 大小 880540184
|+ 定位头 (子条目将被跳过)
|+ EBML void: 大小 4027
|+ 剪辑信息
| + 时间戳缩放: 1000000
| + 混流应用程序: libebml v1.3.5 + libmatroska v1.4.8
| + 写入应用程序: mkvmerge v17.0.0 ('Be Ur Friend') 64-bit
| + 时长: 00:45:17.199000000
| + 日期: 2018-10-02 13:32:30 UTC
| + 剪辑 UID: 0xb1 0x6b 0xa9 0xaf 0x75 0x12 0xf5 0xa7 0xad 0xab 0xd6 0xaa 0x19 0xf5 0x91 0xbd
|+ 轨道
| + 轨道
| + 轨道编号: 1 (mkvmerge & mkvextract 的轨道 ID: 0)
| + 轨道 UID: 12099609334088513866
| + 轨道类型: 视频
| + 「紧缩」 标记: 0
| + 编码格式 ID: V_MPEG4/ISO/AVC
| + 编解码器私有数据: 大小 47 (H.264 档次: High @L4.1)
| + 默认帧时长: 00:00:00.040000000 (对应视频轨的 25.000 帧/场每秒)
| + 语言: chi
| + 视频轨道
| + 像素宽度: 1280
| + 像素高度: 720
| + 显示宽度: 1280
| + 显示高度: 720
| + 轨道
| + 轨道编号: 2 (mkvmerge & mkvextract 的轨道 ID: 1)
| + 轨道 UID: 11992976042516049637
| + 轨道类型: 音频
| + 编码格式 ID: A_AAC
| + 编解码器私有数据: 大小 2
| + 默认帧时长: 00:00:00.023219954 (对应视频轨的 43.066 帧/场每秒)
| + 语言: chi
| + 名称: 国语
| + 音频轨
| + 采样率: 44100
| + 声道数: 2
| + 轨道
| + 轨道编号: 3 (mkvmerge & mkvextract 的轨道 ID: 2)
| + 轨道 UID: 9059807628854784062
| + 轨道类型: 音频
| + 「默认轨」 标记: 0
| + 编码格式 ID: A_AAC
| + 编解码器私有数据: 大小 2
| + 默认帧时长: 00:00:00.023219954 (对应视频轨的 43.066 帧/场每秒)
| + 语言: chi
| + 名称: 粤语
| + 音频轨
| + 采样率: 44100
| + 声道数: 2
| + 轨道
| + 轨道编号: 4 (mkvmerge & mkvextract 的轨道 ID: 3)
| + 轨道 UID: 6875262301070943117
| + 轨道类型: 字幕
| + 「紧缩」 标记: 0
| + 编码格式 ID: S_TEXT/UTF8
| + 语言: chi
| + 名称: 简体中文
| + 轨道
| + 轨道编号: 5 (mkvmerge & mkvextract 的轨道 ID: 4)
| + 轨道 UID: 5198950236804616601
| + 轨道类型: 字幕
| + 「默认轨」 标记: 0
| + 「紧缩」 标记: 0
| + 编码格式 ID: S_TEXT/UTF8
| + 语言: chi
| + 名称: 繁体中文
|+ EBML void: 大小 1196
|+ 簇

单件处理

1
2
3
cd D:\software\mkvtoolnix

mkvmerge -o 难兄难弟-01-粤语.mkv --audio-tracks 2 --subtitle-tracks 3,4 难兄难弟-01.mkv

批量处理

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
@echo off
chcp 65001 >nul
setlocal enabledelayedexpansion

REM 定义 mkvmerge 可执行文件路径
set "exe=D:\software\mkvtoolnix\mkvmerge.exe"

REM 输入文件夹路径
set "input=G:\video"

REM 输出文件夹路径
set "output=G:\video\done"

REM 检查 mkvmerge 是否存在
if not exist "%exe%" (
echo "%exe%" not found
goto end
)

REM 检查输入文件夹是否存在
if not exist "%input%" (
echo "%input%" not found
goto end
)

REM 创建输出文件夹(如果不存在)
md "%output%" 2>nul

REM 遍历 G:\video 下的一层子目录
for /d %%a in ("%input%\*") do (
if /i not "%%~nxa"=="done" (
call :process_directory "%%~fa"
)
)

:end
echo All directories processed.
pause
exit /b

:process_directory
REM 获取当前子目录路径
set "subdir=%~1"

REM 定义输出子目录路径
set "output_subdir=%output%\!subdir:%input%\=!"

REM 创建输出子目录(如果不存在)
md "!output_subdir!" 2>nul

REM 遍历当前子目录中的所有 .mkv 文件
for %%b in ("%subdir%\*.mkv") do (
call :process_file "%%b" "!output_subdir!"
)

exit /b

:process_file
REM 获取当前文件路径和输出目录
set "input_file=%~1"
set "output_dir=%~2"

REM 修改输出文件名,在原文件名后添加“粤语”
for %%c in ("%input_file%") do (
set "output_file=%output_dir%\%%~nc-粤语%%~xc"
)

REM 使用 mkvmerge 保留粤语声轨(音频轨 2)
echo Processing "!input_file!"
echo Output will be saved to "!output_file!"
"%exe%" -o "!output_file!" --audio-tracks 2 --default-track-flag 2:yes "!input_file!"

REM 处理完成提示
if !errorlevel! equ 0 (
echo Successfully processed: "!input_file!"
) else (
echo Failed to process: "!input_file!"
)

exit /b

输出效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
G:\video>tree /F
卷 新加卷 的文件夹 PATH 列表
卷序列号为 D423-6A93
G:.
├─1
│ 难兄难弟-01.mkv
│ 难兄难弟-02.mkv

├─2
│ 难兄难弟-06.mkv
│ 难兄难弟-07.mkv

└─done
├─1
│ 难兄难弟-01-粤语.mkv
│ 难兄难弟-02-粤语.mkv

└─2
难兄难弟-06-粤语.mkv
难兄难弟-07-粤语.mkv

hexo版本

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
[root@localhost hexo]# pwd
/root/hexo

[root@localhost hexo]# hexo version
INFO Validating config
hexo: 7.3.0
hexo-cli: 4.3.2
os: linux 5.14.0-427.42.1.el9_4.x86_64 Rocky Linux 9.4 (Blue Onyx)
node: 18.20.4
acorn: 8.11.3
ada: 2.7.8
ares: 1.28.1
base64: 0.5.2
brotli: 1.0.9
cjs_module_lexer: 1.2.2
cldr: 44.1
icu: 74.2
llhttp: 6.1.1
modules: 108
napi: 9
nghttp2: 1.61.0
nghttp3: 0.7.0
ngtcp2: 1.3.0
openssl: 3.0.13+quic
simdutf: 5.2.4
tz: 2024a
undici: 5.28.4
unicode: 15.1
uv: 1.44.2
uvwasi: 0.0.19
v8: 10.2.154.26-node.37
zlib: 1.3.0.1-motley
[root@localhost hexo]#

next版本

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
34
35
36
37
38
39
40
41
[root@localhost next]# pwd
/root/hexo/themes/next

[root@localhost next]# cat package.json
{
"name": "hexo-theme-next",
"version": "7.8.0",
"description": "Elegant and powerful theme for Hexo.",
"main": "gulpfile.js",
"scripts": {
"test": "gulp"
},
"repository": {
"type": "git",
"url": "git+https://github.com/theme-next/hexo-theme-next.git"
},
"keywords": [
"hexo",
"theme",
"next"
],
"author": "NexT <support@theme-next.org> (https://theme-next.org)",
"license": "AGPL-3.0-or-later",
"bugs": {
"url": "https://github.com/theme-next/hexo-theme-next/issues"
},
"homepage": "https://theme-next.org",
"devDependencies": {
"eslint": "^6.8.0",
"eslint-config-theme-next": "^1.1.4",
"gulp": "^4.0.2",
"gulp-eslint": "^6.0.0",
"gulp-shell": "^0.8.0",
"js-yaml": "^3.13.1",
"stylint": "^2.0.0"
},
"engines": {
"node": ">=10.9.0"
}
}
[root@localhost next]#

主题更新

旧版更名

1
2
3
4
[root@localhost hexo]# pwd
/root/hexo

[root@localhost hexo]# mv themes/next themes/next-v7

更新新版

1
git clone https://github.com/next-theme/hexo-theme-next themes/next
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
[root@localhost next]# pwd
/root/hexo/themes/next

[root@localhost next]# ll
total 80
-rw-r--r--. 1 root root 29634 Jan 15 15:48 _config.yml
-rw-r--r--. 1 root root 232 Jan 15 15:27 crowdin.yml
drwxr-xr-x. 4 root root 82 Jan 15 15:27 docs
-rw-r--r--. 1 root root 79 Jan 15 15:27 eslint.config.js
drwxr-xr-x. 2 root root 4096 Jan 15 15:27 languages
drwxr-xr-x. 6 root root 4096 Jan 15 15:27 layout
-rw-r--r--. 1 root root 2955 Jan 15 15:27 LICENSE.md
-rw-r--r--. 1 root root 1148 Jan 15 15:27 package.json
-rw-r--r--. 1 root root 9484 Jan 15 15:27 README.md
-rw-r--r--. 1 root root 41 Jan 15 15:27 renovate.json
drwxr-xr-x. 6 root root 62 Jan 15 15:27 scripts
drwxr-xr-x. 5 root root 41 Jan 15 15:27 source
drwxr-xr-x. 5 root root 65 Jan 15 15:27 test
-rw-r--r--. 1 root root 4836 Jan 15 15:27 _vendors.yml
[root@localhost next]# cat package.json
{
"name": "hexo-theme-next",
"version": "8.22.0",
"description": "Elegant and powerful theme for Hexo.",
"main": "package.json",
"files": [
"docs",
"languages",
"layout",
"scripts",
"source",
"_config.yml",
"_vendors.yml"
],
"scripts": {
"eslint": "eslint scripts/ source/js test/",
"prepare": "node .githooks/install.js",
"stylint": "stylelint source/css/ --ip source/css/_common/scaffolding/highlight/index.styl",
"test": "mocha test/index.js",
"test-cov": "c8 npm test"
},
"repository": "next-theme/hexo-theme-next",
"keywords": [
"hexo",
"theme",
"next"
],
"author": "NexT (https://theme-next.js.org)",
"license": "AGPL-3.0-only",
"bugs": {
"url": "https://github.com/next-theme/hexo-theme-next/issues"
},
"homepage": "https://theme-next.js.org",
"devDependencies": {
"@next-theme/eslint-config": "0.0.4",
"c8": "10.1.3",
"chai": "4.5.0",
"eslint": "9.17.0",
"hexo": "7.3.0",
"hexo-renderer-marked": "6.3.0",
"js-yaml": "4.1.0",
"mocha": "11.0.1",
"stylelint": "16.12.0",
"stylelint-stylus": "1.0.0"
}
}
[root@localhost next]#

配置修改

主题配置修改

1
vi themes/next-v7/_config.yml (vi多视窗对照编辑  :sp themes/next/_config.yml)

开启mermaid

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
(站点配置文件_config.yml添加 - mermaid)

[root@localhost hexo]# pwd
/root/hexo

[root@localhost hexo]# vi _config.yml
highlight:
line_number: true
auto_detect: false
tab_replace: ''
wrap: true
hljs: false
exclude_languages:
- mermaid

(主题配置文件_config.yml开启mermaid)

[root@localhost next]# pwd
/root/hexo/themes/next

[root@localhost next]# vi _config.yml

mermaid:
enable: true

最后测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[root@localhost hexo]# hexo clean
INFO Validating config
INFO Deleted database.
[root@localhost hexo]# hexo s
INFO Validating config
INFO ==================================
███╗ ██╗███████╗██╗ ██╗████████╗
████╗ ██║██╔════╝╚██╗██╔╝╚══██╔══╝
██╔██╗ ██║█████╗ ╚███╔╝ ██║
██║╚██╗██║██╔══╝ ██╔██╗ ██║
██║ ╚████║███████╗██╔╝ ██╗ ██║

╚═╝ ╚═══╝╚══════╝╚═╝ ╚═╝ ╚═╝
========================================

NexT version 8.22.0

Documentation: https://theme-next.js.org
========================================

INFO Start processing
INFO Hexo is running at http://localhost:4000/ . Press Ctrl+C to stop.

点击查看Mermaid效果

hexo: 7.3.0

hexo-theme-next 8.22.0

流程图

1
2
3
4
5
6
7
8
9
graph TD;

A-->B;

A-->C;

B-->D;

C-->D;
graph TD;

    A-->B;

    A-->C;

    B-->D;

    C-->D;
1
2
3
4
5
6
graph TD 
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
C -->|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
graph TD 
	A[Christmas] -->|Get money| B(Go shopping) 
	B --> C{Let me think} 
	C -->|One| D[Laptop] 
	C -->|Two| E[iPhone] 
	C -->|Three| F[fa:fa-car Car]

时序图

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

participant Alice

participant Bob

Alice->>John: Hello John, how are you?

loop Healthcheck

John->>John: Fight against hypochondria

end

Note right of John: Rational thoughts <br/>prevail!

John-->>Alice: Great!

John->>Bob: How about you?

Bob-->>John: Jolly good!
sequenceDiagram

	participant Alice

	participant Bob

	Alice->>John: Hello John, how are you?

	loop Healthcheck

    	John->>John: Fight against hypochondria

	end

	Note right of John: Rational thoughts <br/>prevail!

	John-->>Alice: Great!

	John->>Bob: How about you?

	Bob-->>John: Jolly good!

甘特图

1
2
3
4
5
6
7
8
9
10
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram to mermaid
excludes weekdays 2025-01-10

section A section
Completed task :done, des1, 2025-01-06,2025-01-08
Active task :active, des2, 2025-01-09, 3d
Future task : des3, after des2, 5d
Future task2 : des4, after des3, 5d
gantt
dateFormat  YYYY-MM-DD
title Adding GANTT diagram to mermaid
excludes weekdays 2025-01-10

section A section
Completed task            :done,    des1, 2025-01-06,2025-01-08
Active task               :active,  des2, 2025-01-09, 3d
Future task               :         des3, after des2, 5d
Future task2               :         des4, after des3, 5d

文件说明

  • gdtv_to_epg.log 日志文件
  • epg.xml XMLTV格式文件
  • gdtv_to_epg.py 电子节目表抓取
  • git_commit.sh 日志提交脚本文件
  • /etc/init.d/gdtv_to_epg 开机执行脚本
  • /etc/rc.local 开机执行脚本

改清华源

vi /etc/opkg/distfeeds.conf

1
2
3
4
5
6
src/gz openwrt_core http://mirrors.tuna.tsinghua.edu.cn/lede/releases/23.05.4/targets/ramips/mt7620/packages
src/gz openwrt_base http://mirrors.tuna.tsinghua.edu.cn/lede/releases/23.05.4/packages/mipsel_24kc/base
src/gz openwrt_luci http://mirrors.tuna.tsinghua.edu.cn/lede/releases/23.05.4/packages/mipsel_24kc/luci
src/gz openwrt_packages http://mirrors.tuna.tsinghua.edu.cn/lede/releases/23.05.4/packages/mipsel_24kc/packages
src/gz openwrt_routing http://mirrors.tuna.tsinghua.edu.cn/lede/releases/23.05.4/packages/mipsel_24kc/routing
src/gz openwrt_telephony http://mirrors.tuna.tsinghua.edu.cn/lede/releases/23.05.4/packages/mipsel_24kc/telephony

安装配置git

1
2
3
4
5
6
7
8
opkg update
opkg install git
opkg install openssh-keygen
opkg install openssh-client
cd /www
git init
ssh-keygen
ssh -T git@gitee.com

抓取源码

/www/gdtv_to_epg.py

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import datetime
import requests
import warnings
import logging
from bs4 import BeautifulSoup as bs
from xml.etree.ElementTree import Element, SubElement, ElementTree

# 日志配置
logging.basicConfig(
filename="/www/gdtv_to_epg.log", # 日志文件路径
level=logging.INFO, # 日志级别
format="%(asctime)s - %(levelname)s - %(message)s",
filemode="w" # 每次运行脚本时覆盖日志
)

# 定义请求头,模拟浏览器访问
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}

# 忽略 XMLParsedAsHTMLWarning
warnings.filterwarnings('ignore')

# 获取广东电视台频道列表
def get_channels_gdtv():
logging.info("开始获取频道列表...")
url = 'http://epg.gdtv.cn/f/1.xml'
try:
res = requests.get(url, headers=headers, timeout=8)
res.encoding = 'utf-8'
soup = bs(res.text, 'html.parser')
contents = soup.select('channel')
channels = []
for content in contents:
channel_id = content.attrs['id']
name = content.ctitle.text.strip()
channels.append({'id': channel_id, 'name': name})
logging.info(f"获取到 {len(channels)} 个频道")
return channels
except requests.exceptions.RequestException as e:
logging.error(f"获取频道列表失败: {e}")
return []

# 处理节目标题中的 HTML 实体和标签
def clean_html(text):
text = bs(text, "html.parser").get_text()
return text.replace('<br />', '\n').replace('<br>', '\n').strip()

# 获取指定日期范围内的节目表
def get_epgs_gdtv(channel_id, start_date, end_date):
logging.info(f"开始抓取频道 {channel_id} 的节目表...")
epgs = []
current_date = start_date
while current_date <= end_date:
url = f'http://epg.gdtv.cn/f/{channel_id}/{current_date.strftime("%Y-%m-%d")}.xml'
try:
res = requests.get(url, headers=headers, timeout=8)
res.encoding = 'utf-8'
soup = bs(res.text, 'html.parser')
epgs_contents = soup.select('content')

for epga in epgs_contents:
starttime = datetime.datetime.fromtimestamp(int(epga.attrs['time1']))
endtime = datetime.datetime.fromtimestamp(int(epga.attrs['time2']))
title = clean_html(epga.get_text())
epgs.append({
'title': title,
'start': starttime,
'end': endtime
})
logging.info(f"完成抓取频道 {channel_id} {current_date} 的节目表,共 {len(epgs)} 条节目")
except requests.exceptions.RequestException as e:
logging.error(f"抓取频道 {channel_id} {current_date} 的节目表失败: {e}")
current_date += datetime.timedelta(days=1)
return epgs

# 创建 XMLTV 文件
def create_epg_xml(channels, epg_data, output_file):
logging.info("开始生成 XMLTV 文件...")
tv = Element('tv')

for channel in channels:
channel_element = SubElement(tv, 'channel', id=channel['id'])
display_name = SubElement(channel_element, 'display-name')
display_name.text = channel['name']

for channel_id, programs in epg_data.items():
for program in programs:
programme = SubElement(tv, 'programme', start=program['start'].strftime('%Y%m%d%H%M%S +0800'),
stop=program['end'].strftime('%Y%m%d%H%M%S +0800'),
channel=channel_id)
title = SubElement(programme, 'title')
title.text = program['title']

tree = ElementTree(tv)
tree.write(output_file, encoding='utf-8', xml_declaration=True)
logging.info(f"XMLTV 文件生成完成: {output_file}")

# 主函数
if __name__ == "__main__":
today = datetime.datetime.now().date()
start_date = today - datetime.timedelta(days=6)
end_date = today + datetime.timedelta(days=2)

try:
logging.info("脚本开始执行")

channels = get_channels_gdtv()
if not channels:
logging.error("没有获取到频道列表,脚本将结束执行。")
exit(1) # 如果未获取到频道列表,则退出

epg_data = {}
for channel in channels:
channel_id = channel['id']
epg_data[channel_id] = get_epgs_gdtv(channel_id, start_date, end_date)

output_file = "/www/epg.xml"
create_epg_xml(channels, epg_data, output_file)

logging.info(f"完成!EPG 文件已保存为 {output_file}")
except Exception as e:
logging.error(f"脚本执行过程中发生错误: {e}")


开机脚本

/etc/rc.local

1
2
3
4
5
6
# Put your custom commands here that should be executed once
# the system init finished. By default this file does nothing.

ntpd -q -p pool.ntp.org

exit 0

/etc/init.d/gdtv_to_epg

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/sh /etc/rc.common
# OpenWrt init script for gdtv_to_epg

START=99
USE_PROCD=1

start_service() {
# 第一个任务,延迟 180 秒执行
procd_open_instance
procd_set_param command /bin/sh -c "sleep 180 && /usr/bin/python /www/gdtv_to_epg.py"
procd_set_param network 1
procd_close_instance

# 第二个任务,延迟 480 秒执行
procd_open_instance
procd_set_param command /bin/sh -c "sleep 480 && /bin/sh /www/git_commit.sh"
procd_set_param network 1
procd_close_instance
}

提交脚本

/www/git_commit.sh

1
2
3
4
5
6
#!/bin/sh
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
cd /www || exit 1 # 进入 Git 仓库的工作目录
git add . # 添加所有修改
git commit -m "更新日志" # 提交修改
git push origin master # 推送到远程仓库

日志文件

/www/gdtv_to_epg.log

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
2025-01-02 18:02:36,843 - INFO - 脚本开始执行
2025-01-02 18:02:36,846 - INFO - 开始获取频道列表...
2025-01-02 18:02:37,149 - INFO - 获取到 15 个频道
2025-01-02 18:02:37,154 - INFO - 开始抓取频道 1 的节目表...
2025-01-02 18:02:37,423 - INFO - 完成抓取频道 1 2024-12-27 的节目表,共 28 条节目
2025-01-02 18:02:37,686 - INFO - 完成抓取频道 1 2024-12-28 的节目表,共 58 条节目
2025-01-02 18:02:37,948 - INFO - 完成抓取频道 1 2024-12-29 的节目表,共 88 条节目
2025-01-02 18:02:38,193 - INFO - 完成抓取频道 1 2024-12-30 的节目表,共 117 条节目
2025-01-02 18:02:38,451 - INFO - 完成抓取频道 1 2024-12-31 的节目表,共 146 条节目
2025-01-02 18:02:38,688 - INFO - 完成抓取频道 1 2025-01-01 的节目表,共 173 条节目
2025-01-02 18:02:38,909 - INFO - 完成抓取频道 1 2025-01-02 的节目表,共 202 条节目
2025-01-02 18:02:39,124 - INFO - 完成抓取频道 1 2025-01-03 的节目表,共 230 条节目
2025-01-02 18:02:39,383 - INFO - 完成抓取频道 1 2025-01-04 的节目表,共 261 条节目
2025-01-02 18:02:39,387 - INFO - 开始抓取频道 2 的节目表...
2025-01-02 18:02:39,559 - INFO - 完成抓取频道 2 2024-12-27 的节目表,共 14 条节目
2025-01-02 18:02:39,701 - INFO - 完成抓取频道 2 2024-12-28 的节目表,共 24 条节目
2025-01-02 18:02:39,856 - INFO - 完成抓取频道 2 2024-12-29 的节目表,共 35 条节目
2025-01-02 18:02:40,033 - INFO - 完成抓取频道 2 2024-12-30 的节目表,共 50 条节目
2025-01-02 18:02:40,201 - INFO - 完成抓取频道 2 2024-12-31 的节目表,共 63 条节目
2025-01-02 18:02:40,358 - INFO - 完成抓取频道 2 2025-01-01 的节目表,共 74 条节目
2025-01-02 18:02:40,538 - INFO - 完成抓取频道 2 2025-01-02 的节目表,共 88 条节目
2025-01-02 18:02:40,716 - INFO - 完成抓取频道 2 2025-01-03 的节目表,共 102 条节目
2025-01-02 18:02:40,902 - INFO - 完成抓取频道 2 2025-01-04 的节目表,共 113 条节目
2025-01-02 18:02:40,905 - INFO - 开始抓取频道 6 的节目表...
2025-01-02 18:02:41,234 - INFO - 完成抓取频道 6 2024-12-27 的节目表,共 44 条节目
2025-01-02 18:02:41,558 - INFO - 完成抓取频道 6 2024-12-28 的节目表,共 88 条节目
2025-01-02 18:02:41,888 - INFO - 完成抓取频道 6 2024-12-29 的节目表,共 133 条节目
2025-01-02 18:02:42,221 - INFO - 完成抓取频道 6 2024-12-30 的节目表,共 177 条节目
2025-01-02 18:02:42,532 - INFO - 完成抓取频道 6 2024-12-31 的节目表,共 221 条节目
2025-01-02 18:02:42,873 - INFO - 完成抓取频道 6 2025-01-01 的节目表,共 266 条节目
2025-01-02 18:02:43,201 - INFO - 完成抓取频道 6 2025-01-02 的节目表,共 310 条节目
2025-01-02 18:02:43,537 - INFO - 完成抓取频道 6 2025-01-03 的节目表,共 355 条节目
2025-01-02 18:02:44,060 - INFO - 完成抓取频道 6 2025-01-04 的节目表,共 399 条节目
2025-01-02 18:02:44,064 - INFO - 开始抓取频道 4 的节目表...
2025-01-02 18:02:44,279 - INFO - 完成抓取频道 4 2024-12-27 的节目表,共 20 条节目
2025-01-02 18:02:44,487 - INFO - 完成抓取频道 4 2024-12-28 的节目表,共 40 条节目
2025-01-02 18:02:44,694 - INFO - 完成抓取频道 4 2024-12-29 的节目表,共 62 条节目
2025-01-02 18:02:44,915 - INFO - 完成抓取频道 4 2024-12-30 的节目表,共 84 条节目
2025-01-02 18:02:45,122 - INFO - 完成抓取频道 4 2024-12-31 的节目表,共 104 条节目
2025-01-02 18:02:45,580 - INFO - 完成抓取频道 4 2025-01-01 的节目表,共 122 条节目
2025-01-02 18:02:45,796 - INFO - 完成抓取频道 4 2025-01-02 的节目表,共 137 条节目
2025-01-02 18:02:45,983 - INFO - 完成抓取频道 4 2025-01-03 的节目表,共 151 条节目
2025-01-02 18:02:46,180 - INFO - 完成抓取频道 4 2025-01-04 的节目表,共 166 条节目
2025-01-02 18:02:46,183 - INFO - 开始抓取频道 3 的节目表...
2025-01-02 18:02:46,442 - INFO - 完成抓取频道 3 2024-12-27 的节目表,共 24 条节目
2025-01-02 18:02:46,742 - INFO - 完成抓取频道 3 2024-12-28 的节目表,共 56 条节目
2025-01-02 18:02:47,028 - INFO - 完成抓取频道 3 2024-12-29 的节目表,共 86 条节目
2025-01-02 18:02:47,346 - INFO - 完成抓取频道 3 2024-12-30 的节目表,共 118 条节目
2025-01-02 18:02:47,665 - INFO - 完成抓取频道 3 2024-12-31 的节目表,共 152 条节目
2025-01-02 18:02:47,990 - INFO - 完成抓取频道 3 2025-01-01 的节目表,共 181 条节目
2025-01-02 18:02:48,302 - INFO - 完成抓取频道 3 2025-01-02 的节目表,共 212 条节目
2025-01-02 18:02:48,540 - INFO - 完成抓取频道 3 2025-01-03 的节目表,共 236 条节目
2025-01-02 18:02:48,781 - INFO - 完成抓取频道 3 2025-01-04 的节目表,共 269 条节目
2025-01-02 18:02:48,785 - INFO - 开始抓取频道 14 的节目表...
2025-01-02 18:02:48,940 - INFO - 完成抓取频道 14 2024-12-27 的节目表,共 18 条节目
2025-01-02 18:02:49,153 - INFO - 完成抓取频道 14 2024-12-28 的节目表,共 41 条节目
2025-01-02 18:02:49,379 - INFO - 完成抓取频道 14 2024-12-29 的节目表,共 66 条节目
2025-01-02 18:02:49,566 - INFO - 完成抓取频道 14 2024-12-30 的节目表,共 84 条节目
2025-01-02 18:02:49,744 - INFO - 完成抓取频道 14 2024-12-31 的节目表,共 101 条节目
2025-01-02 18:02:49,931 - INFO - 完成抓取频道 14 2025-01-01 的节目表,共 119 条节目
2025-01-02 18:02:50,117 - INFO - 完成抓取频道 14 2025-01-02 的节目表,共 136 条节目
2025-01-02 18:02:50,326 - INFO - 完成抓取频道 14 2025-01-03 的节目表,共 154 条节目
2025-01-02 18:02:50,546 - INFO - 完成抓取频道 14 2025-01-04 的节目表,共 177 条节目
2025-01-02 18:02:50,550 - INFO - 开始抓取频道 8 的节目表...
2025-01-02 18:02:50,736 - INFO - 完成抓取频道 8 2024-12-27 的节目表,共 18 条节目
2025-01-02 18:02:50,936 - INFO - 完成抓取频道 8 2024-12-28 的节目表,共 38 条节目
2025-01-02 18:02:51,162 - INFO - 完成抓取频道 8 2024-12-29 的节目表,共 60 条节目
2025-01-02 18:02:51,470 - INFO - 完成抓取频道 8 2024-12-30 的节目表,共 79 条节目
2025-01-02 18:02:51,697 - INFO - 完成抓取频道 8 2024-12-31 的节目表,共 98 条节目
2025-01-02 18:02:51,900 - INFO - 完成抓取频道 8 2025-01-01 的节目表,共 117 条节目
2025-01-02 18:02:52,087 - INFO - 完成抓取频道 8 2025-01-02 的节目表,共 136 条节目
2025-01-02 18:02:52,293 - INFO - 完成抓取频道 8 2025-01-03 的节目表,共 156 条节目
2025-01-02 18:02:52,397 - INFO - 完成抓取频道 8 2025-01-04 的节目表,共 156 条节目
2025-01-02 18:02:52,401 - INFO - 开始抓取频道 13 的节目表...
2025-01-02 18:02:52,679 - INFO - 完成抓取频道 13 2024-12-27 的节目表,共 34 条节目
2025-01-02 18:02:52,966 - INFO - 完成抓取频道 13 2024-12-28 的节目表,共 70 条节目
2025-01-02 18:02:53,260 - INFO - 完成抓取频道 13 2024-12-29 的节目表,共 105 条节目
2025-01-02 18:02:53,368 - INFO - 完成抓取频道 13 2024-12-30 的节目表,共 105 条节目
2025-01-02 18:02:53,482 - INFO - 完成抓取频道 13 2024-12-31 的节目表,共 105 条节目
2025-01-02 18:02:53,592 - INFO - 完成抓取频道 13 2025-01-01 的节目表,共 105 条节目
2025-01-02 18:02:53,707 - INFO - 完成抓取频道 13 2025-01-02 的节目表,共 105 条节目
2025-01-02 18:02:53,821 - INFO - 完成抓取频道 13 2025-01-03 的节目表,共 105 条节目
2025-01-02 18:02:53,923 - INFO - 完成抓取频道 13 2025-01-04 的节目表,共 105 条节目
2025-01-02 18:02:53,927 - INFO - 开始抓取频道 17 的节目表...
2025-01-02 18:02:54,080 - INFO - 完成抓取频道 17 2024-12-27 的节目表,共 10 条节目
2025-01-02 18:02:54,230 - INFO - 完成抓取频道 17 2024-12-28 的节目表,共 19 条节目
2025-01-02 18:02:54,385 - INFO - 完成抓取频道 17 2024-12-29 的节目表,共 28 条节目
2025-01-02 18:02:54,549 - INFO - 完成抓取频道 17 2024-12-30 的节目表,共 39 条节目
2025-01-02 18:02:54,712 - INFO - 完成抓取频道 17 2024-12-31 的节目表,共 50 条节目
2025-01-02 18:02:54,881 - INFO - 完成抓取频道 17 2025-01-01 的节目表,共 61 条节目
2025-01-02 18:02:55,054 - INFO - 完成抓取频道 17 2025-01-02 的节目表,共 72 条节目
2025-01-02 18:02:55,216 - INFO - 完成抓取频道 17 2025-01-03 的节目表,共 82 条节目
2025-01-02 18:02:55,653 - INFO - 完成抓取频道 17 2025-01-04 的节目表,共 90 条节目
2025-01-02 18:02:55,657 - INFO - 开始抓取频道 16 的节目表...
2025-01-02 18:02:55,832 - INFO - 完成抓取频道 16 2024-12-27 的节目表,共 19 条节目
2025-01-02 18:02:56,003 - INFO - 完成抓取频道 16 2024-12-28 的节目表,共 39 条节目
2025-01-02 18:02:56,222 - INFO - 完成抓取频道 16 2024-12-29 的节目表,共 60 条节目
2025-01-02 18:02:56,411 - INFO - 完成抓取频道 16 2024-12-30 的节目表,共 79 条节目
2025-01-02 18:02:56,721 - INFO - 完成抓取频道 16 2024-12-31 的节目表,共 97 条节目
2025-01-02 18:02:56,931 - INFO - 完成抓取频道 16 2025-01-01 的节目表,共 113 条节目
2025-01-02 18:02:57,164 - INFO - 完成抓取频道 16 2025-01-02 的节目表,共 129 条节目
2025-01-02 18:02:57,337 - INFO - 完成抓取频道 16 2025-01-03 的节目表,共 144 条节目
2025-01-02 18:02:57,503 - INFO - 完成抓取频道 16 2025-01-04 的节目表,共 157 条节目
2025-01-02 18:02:57,506 - INFO - 开始抓取频道 18 的节目表...
2025-01-02 18:02:57,657 - INFO - 完成抓取频道 18 2024-12-27 的节目表,共 9 条节目
2025-01-02 18:02:57,809 - INFO - 完成抓取频道 18 2024-12-28 的节目表,共 17 条节目
2025-01-02 18:02:57,944 - INFO - 完成抓取频道 18 2024-12-29 的节目表,共 25 条节目
2025-01-02 18:02:58,106 - INFO - 完成抓取频道 18 2024-12-30 的节目表,共 36 条节目
2025-01-02 18:02:58,258 - INFO - 完成抓取频道 18 2024-12-31 的节目表,共 46 条节目
2025-01-02 18:02:58,409 - INFO - 完成抓取频道 18 2025-01-01 的节目表,共 56 条节目
2025-01-02 18:02:58,559 - INFO - 完成抓取频道 18 2025-01-02 的节目表,共 66 条节目
2025-01-02 18:02:58,709 - INFO - 完成抓取频道 18 2025-01-03 的节目表,共 76 条节目
2025-01-02 18:02:58,858 - INFO - 完成抓取频道 18 2025-01-04 的节目表,共 84 条节目
2025-01-02 18:02:58,861 - INFO - 开始抓取频道 7 的节目表...
2025-01-02 18:02:59,074 - INFO - 完成抓取频道 7 2024-12-27 的节目表,共 21 条节目
2025-01-02 18:02:59,295 - INFO - 完成抓取频道 7 2024-12-28 的节目表,共 42 条节目
2025-01-02 18:02:59,487 - INFO - 完成抓取频道 7 2024-12-29 的节目表,共 60 条节目
2025-01-02 18:02:59,711 - INFO - 完成抓取频道 7 2024-12-30 的节目表,共 82 条节目
2025-01-02 18:02:59,927 - INFO - 完成抓取频道 7 2024-12-31 的节目表,共 105 条节目
2025-01-02 18:03:00,098 - INFO - 完成抓取频道 7 2025-01-01 的节目表,共 125 条节目
2025-01-02 18:03:00,264 - INFO - 完成抓取频道 7 2025-01-02 的节目表,共 143 条节目
2025-01-02 18:03:00,345 - INFO - 完成抓取频道 7 2025-01-03 的节目表,共 143 条节目
2025-01-02 18:03:00,413 - INFO - 完成抓取频道 7 2025-01-04 的节目表,共 143 条节目
2025-01-02 18:03:00,417 - INFO - 开始抓取频道 33 的节目表...
2025-01-02 18:03:00,659 - INFO - 完成抓取频道 33 2024-12-27 的节目表,共 32 条节目
2025-01-02 18:03:00,901 - INFO - 完成抓取频道 33 2024-12-28 的节目表,共 61 条节目
2025-01-02 18:03:01,111 - INFO - 完成抓取频道 33 2024-12-29 的节目表,共 88 条节目
2025-01-02 18:03:01,359 - INFO - 完成抓取频道 33 2024-12-30 的节目表,共 122 条节目
2025-01-02 18:03:01,599 - INFO - 完成抓取频道 33 2024-12-31 的节目表,共 155 条节目
2025-01-02 18:03:01,883 - INFO - 完成抓取频道 33 2025-01-01 的节目表,共 187 条节目
2025-01-02 18:03:02,150 - INFO - 完成抓取频道 33 2025-01-02 的节目表,共 224 条节目
2025-01-02 18:03:02,384 - INFO - 完成抓取频道 33 2025-01-03 的节目表,共 256 条节目
2025-01-02 18:03:02,461 - INFO - 完成抓取频道 33 2025-01-04 的节目表,共 256 条节目
2025-01-02 18:03:02,465 - INFO - 开始抓取频道 31 的节目表...
2025-01-02 18:03:02,541 - INFO - 完成抓取频道 31 2024-12-27 的节目表,共 3 条节目
2025-01-02 18:03:02,657 - INFO - 完成抓取频道 31 2024-12-28 的节目表,共 12 条节目
2025-01-02 18:03:02,746 - INFO - 完成抓取频道 31 2024-12-29 的节目表,共 15 条节目
2025-01-02 18:03:02,833 - INFO - 完成抓取频道 31 2024-12-30 的节目表,共 18 条节目
2025-01-02 18:03:02,923 - INFO - 完成抓取频道 31 2024-12-31 的节目表,共 21 条节目
2025-01-02 18:03:03,015 - INFO - 完成抓取频道 31 2025-01-01 的节目表,共 24 条节目
2025-01-02 18:03:03,098 - INFO - 完成抓取频道 31 2025-01-02 的节目表,共 27 条节目
2025-01-02 18:03:03,195 - INFO - 完成抓取频道 31 2025-01-03 的节目表,共 30 条节目
2025-01-02 18:03:03,280 - INFO - 完成抓取频道 31 2025-01-04 的节目表,共 33 条节目
2025-01-02 18:03:03,284 - INFO - 开始抓取频道 32 的节目表...
2025-01-02 18:03:03,697 - INFO - 完成抓取频道 32 2024-12-27 的节目表,共 66 条节目
2025-01-02 18:03:04,106 - INFO - 完成抓取频道 32 2024-12-28 的节目表,共 127 条节目
2025-01-02 18:03:04,523 - INFO - 完成抓取频道 32 2024-12-29 的节目表,共 193 条节目
2025-01-02 18:03:04,884 - INFO - 完成抓取频道 32 2024-12-30 的节目表,共 248 条节目
2025-01-02 18:03:05,241 - INFO - 完成抓取频道 32 2024-12-31 的节目表,共 303 条节目
2025-01-02 18:03:05,587 - INFO - 完成抓取频道 32 2025-01-01 的节目表,共 355 条节目
2025-01-02 18:03:05,926 - INFO - 完成抓取频道 32 2025-01-02 的节目表,共 408 条节目
2025-01-02 18:03:06,290 - INFO - 完成抓取频道 32 2025-01-03 的节目表,共 465 条节目
2025-01-02 18:03:06,734 - INFO - 完成抓取频道 32 2025-01-04 的节目表,共 516 条节目
2025-01-02 18:03:06,738 - INFO - 开始生成 XMLTV 文件...
2025-01-02 18:03:09,085 - INFO - XMLTV 文件生成完成: /www/epg.xml
2025-01-02 18:03:09,114 - INFO - 完成!EPG 文件已保存为 /www/epg.xml

终端访问

1
http://192.168.1.1/epg.xml

重启直至日志提交完成,全程约需10分钟。

旧站点 数年前部署在github上,hexo发布后是编译过的html文件,源文件.md和配置文件等并不上传到github。年代久远,之前电脑及文件均已无法找到,无法再更新,重新部署记录。

基本思路

  • github新建一个私有仓库,备份源文件等;
  • github新建一个公开仓库,发布博客文件。

准备工作

  • 密钥ssh-keygen -t rsa -b 4096 -C “your_email@example.com
  • 登录github,Repositories,heiok.github.io改名为oldsite,Settings,Pages,Custom domain,删除域名绑定;
  • 新建私有仓库hexo,新建公开仓库heiok.github.io(域名绑定);
  • 测试ssh -T git@github.com

博客发布

  • 安装 npm install -g cnpm –registry=https://registry.npmmirror.com

  • 插件 cnpm install hexo-deployer-git –save

  • 设置 hexo/_config.yml

    1
    2
    3
    4
    5
    6
    # Deployment
    ## Docs: https://hexo.io/docs/one-command-deployment
    deploy:
    type: git
    repo: git@github.com:heiok/heiok.github.io.git
    branch: main
  • 发布

    1
    2
    3
    hexo clean   // 清除缓存
    hexo g // 生成静态网页
    hexo d // 开始部署

备份推送

如果远程仓库已经有内容,先拉取远程内容解决冲突后再推送:

1
2
3
4
5
6
7
git pull origin main --rebase
git init
git remote add origin git@github.com:heiok/hexo.git
git checkout -b main
git add .
git commit -m "blog source files backup"
git push origin main

旧站处理

站点改名为oldsite后,原站点CSS样式需要处理。

1
2
3
4
5
6
7
git clone git@github.com:heiok/oldsite.git
find . -name "*.html" -exec sed -i 's|href="/css|href="/oldsite/css|g' {} \;
find . -name "*.html" -exec sed -i 's|src="/js|src="/oldsite/js|g' {} \;
find . -name "*.html" -exec sed -i 's|href="/\([^o][^/]*\)|href="/oldsite/\1|g' {} \;
find . -name "*.html" -exec sed -i 's|href="/"|href="/oldsite"|' {} \;
find . -name "*.html" -exec sed -i 's|src="/images/|src="/oldsite/images/|g' {} \;
find . -name "*.html" -exec sed -i 's|content="/images/|content="/oldsite/images/|g' {} \;

获取广东电视台节目表 环境依赖Python3 + Django4 + Nginx + uWSGI,用于部署WEB项目站点展示节目列表、节目列表下载预览或提供节目列表API接口使用,过于繁杂,以下代码基于Python3抓取官方节目表后直接生成需要的epg.xml,方便部署在OpenWRT路由器上使用。

获取代码

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import datetime
import requests
import warnings
from bs4 import BeautifulSoup as bs
from xml.etree.ElementTree import Element, SubElement, ElementTree

# 定义请求头,模拟浏览器访问
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36'
}

# 忽略 XMLParsedAsHTMLWarning
warnings.filterwarnings('ignore')

# 获取广东电视台频道列表
def get_channels_gdtv():
url = 'http://epg.gdtv.cn/f/1.xml' # 获取广东电视台频道列表的XML文件
res = requests.get(url, headers=headers)
res.encoding = 'utf-8'
soup = bs(res.text, 'html.parser')
contents = soup.select('channel')
channels = []

for content in contents:
channel_id = content.attrs['id']
name = content.ctitle.text.strip() # 使用 strip() 清理可能的空格和换行
channels.append({'id': channel_id, 'name': name})
return channels

# 处理节目标题中的 HTML 实体和标签
def clean_html(text):
# 将 HTML 实体转换为普通字符(例如 &amp; -> &)
text = bs(text, "html.parser").get_text()
return text.replace('<br />', '\n').replace('<br>', '\n').strip()

# 获取指定日期范围内的节目表
def get_epgs_gdtv(channel_id, start_date, end_date):
epgs = []
current_date = start_date
while current_date <= end_date:
url = f'http://epg.gdtv.cn/f/{channel_id}/{current_date.strftime("%Y-%m-%d")}.xml'
res = requests.get(url, headers=headers, timeout=8)
res.encoding = 'utf-8'
soup = bs(res.text, 'html.parser')
epgs_contents = soup.select('content')

for epga in epgs_contents:
starttime = datetime.datetime.fromtimestamp(int(epga.attrs['time1']))
endtime = datetime.datetime.fromtimestamp(int(epga.attrs['time2']))
title = clean_html(epga.get_text())
epgs.append({
'title': title,
'start': starttime,
'end': endtime
})
current_date += datetime.timedelta(days=1)
return epgs

# 创建 XMLTV 文件
def create_epg_xml(channels, epg_data, output_file):
tv = Element('tv')

# 添加频道信息
for channel in channels:
channel_element = SubElement(tv, 'channel', id=channel['id'])
display_name = SubElement(channel_element, 'display-name')
display_name.text = channel['name']

# 添加节目表
for channel_id, programs in epg_data.items():
for program in programs:
programme = SubElement(tv, 'programme', start=program['start'].strftime('%Y%m%d%H%M%S +0800'),
stop=program['end'].strftime('%Y%m%d%H%M%S +0800'),
channel=channel_id)
title = SubElement(programme, 'title')
title.text = program['title']

# 保存为文件
tree = ElementTree(tv)
tree.write(output_file, encoding='utf-8', xml_declaration=True)

# 主函数
if __name__ == "__main__":
today = datetime.datetime.now().date()
start_date = today - datetime.timedelta(days=6) # 六天前
end_date = today + datetime.timedelta(days=2) # 两天后

print("获取频道列表...")
channels = get_channels_gdtv()

epg_data = {}
print("抓取节目表...")
for channel in channels:
channel_id = channel['id']
epg_data[channel_id] = get_epgs_gdtv(channel_id, start_date, end_date)

print("生成 XMLTV 文件...")
output_file = "epg.xml"
create_epg_xml(channels, epg_data, output_file)
print(f"完成!EPG 文件已保存为 {output_file}")

执行代码

1
2
3
4
5
[root@localhost IPTV]# python gdtv_to_epg.py
获取频道列表...
抓取节目表...
生成 XMLTV 文件...
完成!EPG 文件已保存为 epg.xml

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

  1. CCTV-1综合
  2. CCTV-2财经
  3. CCTV-3综艺测试
  4. CCTV-4中文国际
  5. CCTV-5体育测试
  6. CCTV-6电影(测试)
  7. CCTV-7国防军事
  8. CCTV-8电视剧(测试)
  9. CCTV-9纪录
  10. CCTV-10科教
  11. CCTV-11戏曲
  12. CCTV-12社会与法
  13. CCTV-13新闻
  14. CCTV-14少儿
  15. CCTV-15音乐
  16. CGTN
  17. CCTV-17
  18. CCTV-1高清
  19. CCTV5+体育高清
  20. CCTV-2高清
  21. CCTV-3高清测试
  22. CCTV-4高清
  23. CCTV-5高清测试
  24. CCTV-6高清测试
  25. CCTV-7国防军事高清
  26. CCTV-8高清测试
  27. CCTV-9高清
  28. CCTV-10高清
  29. CCTV-11高清
  30. CCTV-12高清
  31. CCTV-13高清
  32. CCTV-14少儿高清
  33. CCTV-15高清
  34. CCTV-17高清
  35. 广东卫视
  36. 广东珠江
  37. 广东新闻
  38. 广东民生
  39. 广东体育
  40. 大湾区卫视
  41. 广东影视
  42. 广东少儿
  43. 广东4K超高清 宽色域AVS2
  44. 广东移动
  45. 南方购物
  46. 岭南戏曲
  47. 广东卫视高清
  48. 广东体育高清
  49. 广东珠江高清
  50. 大湾区卫视高清
  51. 广东影视高清
  52. 广东民生高清
  53. 广东少儿高清
  54. 广东新闻高清
  55. 岭南戏曲高清
  56. 广东珠江超清
  57. VSPN电竞
  58. 精选频道1
  59. 经济科教
  60. 嘉佳卡通
  61. 现代教育
  62. 卡酷动画
  63. 金鹰卡通
  64. 炫动卡通
  65. CETV-1
  66. 山东教育
  67. 财富天下
  68. CETV-2
  69. CETV-4
  70. 经济科教高清
  71. 嘉佳卡通高清
  72. 现代教育高清
  73. 金鹰纪实高清
  74. 上海纪实高清
  75. IPTV谍战剧场
  76. IPTV相声小品
  77. IPTV野外
  78. IPTV法治
  79. 爱电影
  80. 经典电影
  81. 爱大剧
  82. 热播剧场
  83. 爱综艺
  84. 爱体育
  85. 少儿动画
  86. 魅力时尚
  87. 收视指南
  88. 汽摩
  89. 老故事
  90. 国学频道
  91. 兵器科技高清
  92. 电视指南高清
  93. 风云足球高清
  94. 央视台球高清
  95. 高尔夫网球高清
  96. 女性时尚高清
  97. 世界地理高清
  98. 怀旧剧场高清
  99. 风云剧场高清
  100. 央视精品高清
  101. 第一剧场高清
  102. 风云音乐高清
  103. 湖南卫视
  104. 浙江卫视
  105. 江苏卫视
  106. 东方卫视
  107. 安徽卫视
  108. 北京卫视
  109. 天津卫视
  110. 山东卫视
  111. 江西卫视
  112. 深圳卫视
  113. 湖北卫视
  114. 辽宁卫视
  115. 黑龙江卫视
  116. 贵州卫视
  117. 四川卫视
  118. 河南卫视
  119. 云南卫视
  120. 重庆卫视
  121. 河北卫视
  122. 东南卫视
  123. 广西卫视
  124. 吉林卫视
  125. 陕西卫视
  126. 山西卫视
  127. 内蒙古卫视
  128. 青海卫视
  129. 海南卫视
  130. 宁夏卫视
  131. 西藏卫视
  132. 新疆卫视
  133. 甘肃卫视
  134. 兵团卫视
  135. 厦门卫视
  136. 三沙卫视
  137. 湖南卫视高清
  138. 浙江卫视高清
  139. 北京卫视高清
  140. 深圳卫视高清
  141. 东方卫视高清
  142. 福建东南卫视高清
  143. 海南卫视高清

前期准备工作

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
[root@localhost ~]# cat /etc/redhat-release
Rocky Linux release 9.4 (Blue Onyx)

[root@localhost demoCA]# openssl version
OpenSSL 3.0.7 1 Nov 2022 (Library: OpenSSL 3.0.7 1 Nov 2022)

[root@localhost ~]# pwd
/root

[root@localhost ~]# mkdir -p demoCA


[root@localhost ~]# cp /etc/pki/tls/openssl.cnf .


[root@localhost ~]# vi openssl.cnf

[ CA_default ]

dir = /root/demoCA # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several certs with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.

certificate = $dir/cacert.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key


[ policy_match ]
countryName = optional
stateOrProvinceName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional


[root@localhost ~]# cd demoCA/


#root@localhost demoCA]# mkdir newcerts private


[root@localhost demoCA]# chmod 700 private


[root@localhost demoCA]# touch index.txt


[root@localhost demoCA]# echo 01 > serial


[root@localhost demoCA]# tree -L 1
.
├── index.txt
├── newcerts
├── private
└── serial

2 directories, 2 files


newcerts:存放 CA 已签署颁发过的数字证书

private:存放 CA 的私钥

serial:存放证书序列号,可自定义第一张证书的序号(e.g. 0001),之后每新建一张证书,序列号会自动加1

index.txt:存放证书信息

生成CA证书RSA私钥

1
2
3
4
5
6
7
8
9
10
11
12
[root@localhost demoCA]# openssl genrsa -passout pass:google -des3 -out ~/demoCA/private/cakey.pem 2048


[root@localhost demoCA]# tree -L 2
.
├── index.txt
├── newcerts
├── private
│   └── cakey.pem
└── serial

2 directories, 3 files

生成CA的根证书公钥

CA证书签名请求 & 对证书进行自签名

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
34
35
36
37
38
39
[root@localhost demoCA]# openssl req -x509 -passin pass:google -new -nodes -key ~/demoCA/private/cakey.pem -days 3650 -s
ubj "/C=CN/ST=GuangDong/L=GZ/O=Approach/CN=www.heiok.com" -out cacert.pem


[root@localhost demoCA]# tree -L 2
.
├── cacert.pem
├── index.txt
├── newcerts
├── private
│   └── cakey.pem
└── serial

2 directories, 4 files


[root@localhost demoCA]# cat cacert.pem
-----BEGIN CERTIFICATE-----
MIIDkzCCAnugAwIBAgIUV3Ql0iptpwoskmLaWoWD2kMmkgQwDQYJKoZIhvcNAQEL
BQAwWTELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCUd1YW5nRG9uZzELMAkGA1UEBwwC
R1oxETAPBgNVBAoMCEFwcHJvYWNoMRYwFAYDVQQDDA13d3cuaGVpb2suY29tMB4X
DTI0MTIyNTA4MjkwOVoXDTM0MTIyMzA4MjkwOVowWTELMAkGA1UEBhMCQ04xEjAQ
BgNVBAgMCUd1YW5nRG9uZzELMAkGA1UEBwwCR1oxETAPBgNVBAoMCEFwcHJvYWNo
MRYwFAYDVQQDDA13d3cuaGVpb2suY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEA1/hreZ4fTBB4rf3JX1KmnFp5F+JicASvYGgoGsyhYAiHsD5AWvqF
rbuolZqtK6qpxMcFhP7HKyvVM/gtbtWvcdfQFsvcdBOHifKDjnerGRcI6sThY7jg
qI4fJRjNN7wOTpFMS1J6BxUx9x9LMP6NPnhKUqmWqvhExOGOCxqKGkZdgNp1gPri
sWJVqZdoX6hDfbe1n4qkVT6j322rt6+dU+52T8sBkTVc+9dZx67d0d6nhUdl6TnI
Z7qNPmAr7F17IwWHAcGks/qp4izVHCjKljlEg+jFMb1Su1sMQRjyFn1pkAroS8iH
vbhuW6tfX/c8WH/Rry6FlJlvQIcUaSdFKQIDAQABo1MwUTAdBgNVHQ4EFgQUkMyf
n8Vx4qeP/S9cdZ6Du4CuibUwHwYDVR0jBBgwFoAUkMyfn8Vx4qeP/S9cdZ6Du4Cu
ibUwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAIjDmxvVLuJGA
4A8I7QXIhSmFPG2WPems70C2N6hXeybMVN9wGFHp7v9m23Xe83J7wogZMbspRR+Z
tDML/s51P2JQOTQ91eJ6bj21gWQa/Guhb2H8fQtEoXONYfIfIZMIYL2o66GkPOFy
QCeWS3NJdgwDRNcDXIxguZAA0PMnKZkYT5B0G4K0wN9oEqE3+2ZjpF70Wnpo5aWp
1ZbgZFEAhvv6f1Qjc+4GeCVq92b98qXbrkGcim9Vb6ZLhdXFCcJZyxjDJsIBkEW6
OudF00OwP6OWSI5DN4bniXpHcJQQ15CPZdEiGpsHA6Ac6+fb+ENiodbwfdR/eJxX
0g1ALTFR3A==
-----END CERTIFICATE-----

查看 CA 证书的内容

CA证书已包含与密钥文件对应的公钥信息

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
[root@localhost demoCA]# openssl x509 -in cacert.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
57:74:25:d2:2a:6d:a7:0a:2c:92:62:da:5a:85:83:da:43:26:92:04
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = CN, ST = GuangDong, L = GZ, O = Approach, CN = www.heiok.com
Validity
Not Before: Dec 25 08:29:09 2024 GMT
Not After : Dec 23 08:29:09 2034 GMT
Subject: C = CN, ST = GuangDong, L = GZ, O = Approach, CN = www.heiok.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:d7:f8:6b:79:9e:1f:4c:10:78:ad:fd:c9:5f:52:
a6:9c:5a:79:17:e2:62:70:04:af:60:68:28:1a:cc:
a1:60:08:87:b0:3e:40:5a:fa:85:ad:bb:a8:95:9a:
ad:2b:aa:a9:c4:c7:05:84:fe:c7:2b:2b:d5:33:f8:
2d:6e:d5:af:71:d7:d0:16:cb:dc:74:13:87:89:f2:
83:8e:77:ab:19:17:08:ea:c4:e1:63:b8:e0:a8:8e:
1f:25:18:cd:37:bc:0e:4e:91:4c:4b:52:7a:07:15:
31:f7:1f:4b:30:fe:8d:3e:78:4a:52:a9:96:aa:f8:
44:c4:e1:8e:0b:1a:8a:1a:46:5d:80:da:75:80:fa:
e2:b1:62:55:a9:97:68:5f:a8:43:7d:b7:b5:9f:8a:
a4:55:3e:a3:df:6d:ab:b7:af:9d:53:ee:76:4f:cb:
01:91:35:5c:fb:d7:59:c7:ae:dd:d1:de:a7:85:47:
65:e9:39:c8:67:ba:8d:3e:60:2b:ec:5d:7b:23:05:
87:01:c1:a4:b3:fa:a9:e2:2c:d5:1c:28:ca:96:39:
44:83:e8:c5:31:bd:52:bb:5b:0c:41:18:f2:16:7d:
69:90:0a:e8:4b:c8:87:bd:b8:6e:5b:ab:5f:5f:f7:
3c:58:7f:d1:af:2e:85:94:99:6f:40:87:14:69:27:
45:29
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
90:CC:9F:9F:C5:71:E2:A7:8F:FD:2F:5C:75:9E:83:BB:80:AE:89:B5
X509v3 Authority Key Identifier:
90:CC:9F:9F:C5:71:E2:A7:8F:FD:2F:5C:75:9E:83:BB:80:AE:89:B5
X509v3 Basic Constraints: critical
CA:TRUE
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
22:30:e6:c6:f5:4b:b8:91:80:e0:0f:08:ed:05:c8:85:29:85:
3c:6d:96:3d:e9:ac:ef:40:b6:37:a8:57:7b:26:cc:54:df:70:
18:51:e9:ee:ff:66:db:75:de:f3:72:7b:c2:88:19:31:bb:29:
45:1f:99:b4:33:0b:fe:ce:75:3f:62:50:39:34:3d:d5:e2:7a:
6e:3d:b5:81:64:1a:fc:6b:a1:6f:61:fc:7d:0b:44:a1:73:8d:
61:f2:1f:21:93:08:60:bd:a8:eb:a1:a4:3c:e1:72:40:27:96:
4b:73:49:76:0c:03:44:d7:03:5c:8c:60:b9:90:00:d0:f3:27:
29:99:18:4f:90:74:1b:82:b4:c0:df:68:12:a1:37:fb:66:63:
a4:5e:f4:5a:7a:68:e5:a5:a9:d5:96:e0:64:51:00:86:fb:fa:
7f:54:23:73:ee:06:78:25:6a:f7:66:fd:f2:a5:db:ae:41:9c:
8a:6f:55:6f:a6:4b:85:d5:c5:09:c2:59:cb:18:c3:26:c2:01:
90:45:ba:3a:e7:45:d3:43:b0:3f:a3:96:48:8e:43:37:86:e7:
89:7a:47:70:94:10:d7:90:8f:65:d1:22:1a:9b:07:03:a0:1c:
eb:e7:db:f8:43:62:a1:d6:f0:7d:d4:7f:78:9c:57:d2:0d:40:
2d:31:51:dc

生成服务器证书密钥文件 & 证书签名请求

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
34
[root@localhost demoCA]# openssl req -utf8 -newkey rsa:2048 -nodes -keyout client.key -subj "/C=CN/ST=广东省/O=广东省服
务器/CN=广东省服务器" -out client.csr

[root@localhost demoCA]# tree -L 2
.
├── cacert.pem
├── client.csr
├── client.key
├── index.txt
├── newcerts
├── private
│   └── cakey.pem
└── serial

2 directories, 6 files

[root@localhost demoCA]# cat client.csr
-----BEGIN CERTIFICATE REQUEST-----
MIICoDCCAYgCAQAwWzELMAkGA1UEBhMCQ04xEjAQBgNVBAgMCeW5v+S4nOecgTEb
MBkGA1UECgwS5bm/5Lic55yB5pyN5Yqh5ZmoMRswGQYDVQQDDBLlub/kuJznnIHm
nI3liqHlmagwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCyuYovU3Vh
MmZfOZlYYy6SFJq8Xk7ZznhZRI8eTerfe08tqH2L/XWXPnlZWbOrvRME+Njmi6Wv
ZaXyNiWb39GRkxVRMBWYU7OLE8aUdowznTtFeJAnm/gHZhfmUaIMp3R+zyLs5POy
ZJ0o4cD3YVk+ep7FN+uPefrWgc4u3QXZoX011JrCwgP4hMYL7qgytXfQ0Y045oU6
zciKI05XeAlT9+rtiM4k1ee6DZY8GvH5UoNEwC7onDK2BhM9iIu82OscVrgaKNrJ
yDgoUa/8h8I6Ar9a+7w/3/lT+wnq9pWmek2WqNCb4DsystOurHZQCL7orn3z6wCa
L9TntnUL0cbzAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAKTZwHQsRaFPexJoc
rR+qklzdGScCEYJbiB6qk6Q+UFa8l0yO/xnKXQ0iCCbwZ2MtUM2Bw6d/95hlIaq6
ENDrtrGSK2BkUNvocr+IM1YJHdG/jPFyKJanY6AlokQEo03pfuGgRQMlnOu2ZQls
/2EFPBv6CVwidgTY2cqZHGw3cicoPiZ39ikj07P+V+uira1YqUSkyV+xf8M3G5vK
luHBKq71DvJNH+LFJawOpILWReAhIXaxT+6lI17JqCiH9Rs0Srw7/V76Ks6sLpo8
eZr/WxsOCzDvztyhyyiB1QJj5cjnl6wU/g3NhHvo7JjFqobOH86Pa72v53OJ1lHI
Idh1Iw==
-----END CERTIFICATE REQUEST-----

CA签发服务器证书

根据 openssl.cnf 加载CA证书并集合服务器证书签名请求文件来完成签名

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
[root@localhost demoCA]# openssl ca -passin pass:google -config ~/openssl.cnf -in client.csr -out client_cert.pem -batch

Using configuration from /root/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Dec 25 08:55:30 2024 GMT
Not After : Dec 25 08:55:30 2025 GMT
Subject:
countryName = CN
stateOrProvinceName = \U5E7F\U4E1C\U7701
organizationName = \U5E7F\U4E1C\U7701\U670D\U52A1\U5668
commonName = \U5E7F\U4E1C\U7701\U670D\U52A1\U5668
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
E2:AF:5A:FB:F3:B8:25:2C:62:D9:3B:09:EA:1A:65:0E:3E:12:54:18
X509v3 Authority Key Identifier:
90:CC:9F:9F:C5:71:E2:A7:8F:FD:2F:5C:75:9E:83:BB:80:AE:89:B5
Certificate is to be certified until Dec 25 08:55:30 2025 GMT (365 days)

Write out database with 1 new entries
Data Base Updated

[root@localhost demoCA]# tree -L 3
.
├── cacert.pem
├── client_cert.pem
├── client.csr
├── client.key
├── index.txt
├── index.txt.attr
├── index.txt.old
├── newcerts
│   └── 01.pem
├── private
│   └── cakey.pem
├── serial
└── serial.old

2 directories, 11 files

[root@localhost demoCA]# ll
total 36
-rw-r--r--. 1 root root 1302 Dec 25 16:29 cacert.pem
-rw-r--r--. 1 root root 4443 Dec 25 16:55 client_cert.pem
-rw-r--r--. 1 root root 989 Dec 25 16:42 client.csr
-rw-------. 1 root root 1704 Dec 25 16:42 client.key
-rw-r--r--. 1 root root 225 Dec 25 16:55 index.txt
-rw-r--r--. 1 root root 21 Dec 25 16:55 index.txt.attr
-rw-r--r--. 1 root root 0 Dec 25 15:59 index.txt.old
drwxr-xr-x. 2 root root 20 Dec 25 16:55 newcerts
drwx------. 2 root root 23 Dec 25 16:21 private
-rw-r--r--. 1 root root 3 Dec 25 16:55 serial
-rw-r--r--. 1 root root 3 Dec 25 15:59 serial.old


[root@localhost demoCA]# cat client_cert.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=GuangDong, L=GZ, O=Approach, CN=www.heiok.com
Validity
Not Before: Dec 25 08:55:30 2024 GMT
Not After : Dec 25 08:55:30 2025 GMT
Subject: C=CN, ST=\xE5\xB9\xBF\xE4\xB8\x9C\xE7\x9C\x81, O=\xE5\xB9\xBF\xE4\xB8\x9C\xE7\x9C\x81\xE6\x9C\x8D\xE5\x8A\xA1\xE5\x99\xA8, CN=\xE5\xB9\xBF\xE4\xB8\x9C\xE7\x9C\x81\xE6\x9C\x8D\xE5\x8A\xA1\xE5\x99\xA8
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:b2:b9:8a:2f:53:75:61:32:66:5f:39:99:58:63:
2e:92:14:9a:bc:5e:4e:d9:ce:78:59:44:8f:1e:4d:
ea:df:7b:4f:2d:a8:7d:8b:fd:75:97:3e:79:59:59:
b3:ab:bd:13:04:f8:d8:e6:8b:a5:af:65:a5:f2:36:
25:9b:df:d1:91:93:15:51:30:15:98:53:b3:8b:13:
c6:94:76:8c:33:9d:3b:45:78:90:27:9b:f8:07:66:
17:e6:51:a2:0c:a7:74:7e:cf:22:ec:e4:f3:b2:64:
9d:28:e1:c0:f7:61:59:3e:7a:9e:c5:37:eb:8f:79:
fa:d6:81:ce:2e:dd:05:d9:a1:7d:35:d4:9a:c2:c2:
03:f8:84:c6:0b:ee:a8:32:b5:77:d0:d1:8d:38:e6:
85:3a:cd:c8:8a:23:4e:57:78:09:53:f7:ea:ed:88:
ce:24:d5:e7:ba:0d:96:3c:1a:f1:f9:52:83:44:c0:
2e:e8:9c:32:b6:06:13:3d:88:8b:bc:d8:eb:1c:56:
b8:1a:28:da:c9:c8:38:28:51:af:fc:87:c2:3a:02:
bf:5a:fb:bc:3f:df:f9:53:fb:09:ea:f6:95:a6:7a:
4d:96:a8:d0:9b:e0:3b:32:b2:d3:ae:ac:76:50:08:
be:e8:ae:7d:f3:eb:00:9a:2f:d4:e7:b6:75:0b:d1:
c6:f3
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Subject Key Identifier:
E2:AF:5A:FB:F3:B8:25:2C:62:D9:3B:09:EA:1A:65:0E:3E:12:54:18
X509v3 Authority Key Identifier:
90:CC:9F:9F:C5:71:E2:A7:8F:FD:2F:5C:75:9E:83:BB:80:AE:89:B5
Signature Algorithm: sha256WithRSAEncryption
Signature Value:
0a:e7:5a:c0:f6:b5:14:f6:c4:6a:b8:d3:8b:fc:d9:c0:a6:7c:
22:e2:1b:93:db:55:89:44:7a:c3:47:e5:ba:5c:87:27:a9:32:
5b:a7:26:b7:e5:da:52:c8:ca:9e:3d:bc:64:7e:ff:81:78:68:
00:b0:23:1b:8b:9c:73:60:18:bd:7d:2d:5f:d6:41:20:cd:69:
55:13:74:d5:ce:c7:07:86:41:22:69:ee:5c:5a:46:13:83:ef:
46:90:a3:03:aa:f9:fd:a9:a8:2d:ca:3c:77:60:e6:ee:79:03:
7c:3a:33:78:a5:13:c9:4d:df:9b:58:af:e1:d3:41:89:cb:d9:
81:ae:35:01:08:ca:9c:7b:7f:a5:d2:5b:c5:ef:31:34:85:a3:
a6:17:a6:ae:dd:14:d5:0e:88:63:16:50:6c:eb:ff:0b:be:45:
6e:17:eb:65:9a:ab:e8:94:d1:a6:e9:ca:90:9b:8c:08:29:4b:
3f:ef:5d:6c:03:c4:b8:d8:d9:b0:04:80:43:30:31:c9:71:bc:
9b:82:67:b8:37:55:57:a8:47:42:58:43:35:9e:f1:e1:08:0f:
fd:17:f6:a2:92:88:83:c4:a7:1f:5b:af:c4:ac:ec:85:a5:af:
77:a8:79:b3:19:b2:92:9d:7e:0f:9a:20:3e:99:47:a3:48:59:
37:ba:07:ef
-----BEGIN CERTIFICATE-----
MIIDfDCCAmSgAwIBAgIBATANBgkqhkiG9w0BAQsFADBZMQswCQYDVQQGEwJDTjES
MBAGA1UECAwJR3VhbmdEb25nMQswCQYDVQQHDAJHWjERMA8GA1UECgwIQXBwcm9h
Y2gxFjAUBgNVBAMMDXd3dy5oZWlvay5jb20wHhcNMjQxMjI1MDg1NTMwWhcNMjUx
MjI1MDg1NTMwWjBbMQswCQYDVQQGEwJDTjESMBAGA1UECAwJ5bm/5Lic55yBMRsw
GQYDVQQKDBLlub/kuJznnIHmnI3liqHlmagxGzAZBgNVBAMMEuW5v+S4nOecgeac
jeWKoeWZqDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALK5ii9TdWEy
Zl85mVhjLpIUmrxeTtnOeFlEjx5N6t97Ty2ofYv9dZc+eVlZs6u9EwT42OaLpa9l
pfI2JZvf0ZGTFVEwFZhTs4sTxpR2jDOdO0V4kCeb+AdmF+ZRogyndH7PIuzk87Jk
nSjhwPdhWT56nsU36495+taBzi7dBdmhfTXUmsLCA/iExgvuqDK1d9DRjTjmhTrN
yIojTld4CVP36u2IziTV57oNljwa8flSg0TALuicMrYGEz2Ii7zY6xxWuBoo2snI
OChRr/yHwjoCv1r7vD/f+VP7Cer2laZ6TZao0JvgOzKy066sdlAIvuiuffPrAJov
1Oe2dQvRxvMCAwEAAaNNMEswCQYDVR0TBAIwADAdBgNVHQ4EFgQU4q9a+/O4JSxi
2TsJ6hplDj4SVBgwHwYDVR0jBBgwFoAUkMyfn8Vx4qeP/S9cdZ6Du4CuibUwDQYJ
KoZIhvcNAQELBQADggEBAArnWsD2tRT2xGq404v82cCmfCLiG5PbVYlEesNH5bpc
hyepMlunJrfl2lLIyp49vGR+/4F4aACwIxuLnHNgGL19LV/WQSDNaVUTdNXOxweG
QSJp7lxaRhOD70aQowOq+f2pqC3KPHdg5u55A3w6M3ilE8lN35tYr+HTQYnL2YGu
NQEIypx7f6XSW8XvMTSFo6YXpq7dFNUOiGMWUGzr/wu+RW4X62Waq+iU0abpypCb
jAgpSz/vXWwDxLjY2bAEgEMwMclxvJuCZ7g3VVeoR0JYQzWe8eEID/0X9qKSiIPE
px9br8Ss7IWlr3eoebMZspKdfg+aID6ZR6NIWTe6B+8=
-----END CERTIFICATE-----

导出为 PKCS#12 文件

1
2
3
4
5
6
OpenSSL 1.0.2k-fips

[root@localhost demoCA]# openssl pkcs12 -export -in client_cert.pem -inkey client.key -out client.p12

Enter Export Password:
Verifying - Enter Export Password:

Adobe Acrobat添加OpenSSL 3.0.7版本生成的.p12文件会有加密算法与 KDF(密钥派生函数)问题,添加以下参数解决

参数说明:

-certpbe PBE-SHA1-3DES:指定证书的加密算法为 3DES(适用于旧软件)。
-keypbe PBE-SHA1-3DES:指定私钥的加密算法为 3DES。
-macalg SHA1:将 MAC 的算法强制设置为 SHA-1,而不是 OpenSSL 3.x 的默认 SHA-256 或更高。

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

[root@localhost demoCA]# openssl pkcs12 -export -in client_cert.pem -inkey client.key -out client.p12 -certpbe PBE-SHA1-3DES -keypbe PBE-SHA1-3DES -macalg SHA1

Enter Export Password:
Verifying - Enter Export Password:


[root@localhost demoCA]# ll
total 40
-rw-r--r--. 1 root root 1302 Dec 25 16:29 cacert.pem
-rw-r--r--. 1 root root 4443 Dec 25 16:55 client_cert.pem
-rw-r--r--. 1 root root 989 Dec 25 16:42 client.csr
-rw-------. 1 root root 1704 Dec 25 16:42 client.key
-rw-------. 1 root root 2643 Dec 25 17:09 client.p12
-rw-r--r--. 1 root root 225 Dec 25 16:55 index.txt
-rw-r--r--. 1 root root 21 Dec 25 16:55 index.txt.attr
-rw-r--r--. 1 root root 0 Dec 25 15:59 index.txt.old
drwxr-xr-x. 2 root root 20 Dec 25 16:55 newcerts
drwx------. 2 root root 23 Dec 25 16:21 private
-rw-r--r--. 1 root root 3 Dec 25 16:55 serial
-rw-r--r--. 1 root root 3 Dec 25 15:59 serial.old
0%