电影/游戏墙(手风琴动态)及自动生成脚本
手风琴样式的展示墙,鼠标移上去图片会显示完全并且展示描述文字。点击图片会跳转到对应的豆瓣链接
前端代码
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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" /> <meta http-equiv ="X-UA-Compatible" content ="IE=edge" /> <meta name ="viewport" content ="width=device-width, initial-scale=1.0" /> <style > body { font-family : Arial, sans-serif; margin : 0 ; padding : 0 ; } .contain { position : relative; width : 90% ; max-width : 1050px ; margin : 100px auto; overflow : hidden; background : #fff ; border-radius : 10px ; box-shadow : 0 4px 10px rgba (0 , 0 , 0 , 0.1 ); } .contain > ul { display : flex; height : calc (100vh / 2.9 ); justify-content : space-between; list-style : none; padding : 0 ; margin : 0 ; gap : 10px ; } .contain > ul > li { position : relative; width : calc (100% / 6 - 10px ); height : 100% ; transition : width 0.5s ; overflow : hidden; border-left : 2px solid rgba (255 , 255 , 255 , 0.8 ); box-shadow : 0px 0px 20px rgba (0 , 0 , 0 , 0.1 ); } .contain > ul > li :first -child { border-left : none; } .contain > ul > li :hover { width : 500px ; } .contain a { color : #fff ; text-decoration : none; display : flex; height : 100% ; border-radius : 10px ; overflow : hidden; } .contain > ul > li > a > img { width : 100% ; height : 100% ; object-fit : cover; transition : transform 0.5s ; } .contain > ul > li :hover img { transform : scale (1.1 ); } .info { display : none; flex-direction : column; justify-content : center; padding : 20px ; background : rgba (0 , 0 , 0 , 0.5 ); backdrop-filter : blur (10px ); color : white; transition : opacity 0.5s ; opacity : 0 ; } .contain > ul > li :hover .info { display : flex; opacity : 1 ; } .info h2 { margin : 0 ; font-size : 24px ; text-shadow : 2px 2px 4px rgba (0 , 0 , 0 , 0.5 ); line-height : 1.5 ; } .info p { margin : 10px 0 0 ; font-size : 16px ; text-shadow : 1px 1px 3px rgba (0 , 0 , 0 , 0.5 ); line-height : 1.5 ; } body { background-color : #333 ; color : #fff ; } .contain { background : #444 ; box-shadow : 0 4px 10px rgba (0 , 0 , 0 , 0.5 ); } .contain > ul > li { border-left : 2px solid rgba (255 , 255 , 255 , 0.2 ); } .info h2 , .info p { color : #fff ; } .rounded-title { color : white; border-radius : 10px ; padding : 10px 20px ; text-align : center; display : inline-block; box-shadow : 0 4px 6px rgba (0 , 0 , 0 , 0.1 ); font-size : 30px ; } </style > <script > if ( /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i .test ( navigator.userAgent ) ) { alert ( "嘿,这个页面在手机上显示效果可能不太好哦!建议切换到电脑上查看~" ); } </script > </head > <body > <div class ="contain" > <h2 class ="rounded-title" > 那些年看过的影视剧 <i class ="fa-solid fa-face-grin-hearts" > </i > </h2 > <ul > <li > <a href ="https://movie.douban.com/subject/1297110/" > <img src ="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p1833029967.webp" referrerpolicy ="no-referrer" style ="width:auto;height:auto;" /> <div class ="info" > <h2 > 睡美人</h2 > <p > Sleeping Beauty</p > </div > </a > </li > <li > <a href ="https://movie.douban.com/subject/1294408/" > <img src ="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p453788577.webp" referrerpolicy ="no-referrer" style ="width:auto;height:auto;" /> <div class ="info" > <h2 > 音乐之声</h2 > <p > 神!</p > </div > </a > </li > <li > <a href ="https://movie.douban.com/subject/1305697/" > <img src ="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2576327873.webp" referrerpolicy ="no-referrer" style ="width:auto;height:auto;" /> <div class ="info" > <h2 > 桥</h2 > <p > 啊,朋友再见</p > </div > </a > </li > <li > <a href ="https://movie.douban.com/subject/1303075/" > <img src ="https://img9.doubanio.com/view/photo/s_ratio_poster/public/p2549456054.webp" referrerpolicy ="no-referrer" style ="width:auto;height:auto;" /> <div class ="info" > <h2 > 这里的黎明静悄悄</h2 > <p > А зори здесь тихие</p > </div > </a > </li > <li > <a href ="https://movie.douban.com/subject/1291860/" > <img src ="https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2556873379.webp" referrerpolicy ="no-referrer" style ="width:auto;height:auto;" /> <div class ="info" > <h2 > 瓦尔特保卫萨拉热窝</h2 > <p > 看,这座城市就是瓦尔特</p > </div > </a > </li > <li > <a href ="https://movie.douban.com/subject/1293838/" > <img src ="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2500865872.webp" referrerpolicy ="no-referrer" style ="width:auto;height:auto;" /> <div class ="info" > <h2 > 星球大战</h2 > <p > 梦开始的地方</p > </div > </a > </li > </ul > </div > </body > </html >
python 自动生成脚本
movieConvert.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 import pandas as pddf = pd.read_excel(r'。。。。。。.xlsx' ) html_template = """ <ul> {items} </ul> """ item_template = """ <li> <a href="{link}"> <img src="{img}" referrerpolicy="no-referrer" style="width:auto;height:auto;" /> <div class="info"> <h2>{title}</h2> <p>{description}</p> </div> </a> </li> """ all_html_content = "" group_html_content = "" for index, row in df.iterrows(): movie_titles = row[0 ].split('/' ) title = movie_titles[0 ] if len (movie_titles) > 0 else "" description = movie_titles[1 ] if len (movie_titles) > 1 else "" link = row[1 ] img = row[2 ] group_html_content += item_template.format (title=title, description=description, link=link, img=img) if (index + 1 ) % 6 == 0 or index + 1 == len (df): all_html_content += html_template.format (items=group_html_content) group_html_content = "" with open ('output.html' , 'w' , encoding='utf-8' ) as file: file.write(all_html_content) print ('Done!' )
前提是有一个从豆瓣页面爬取下来的看过的电影 excel 表格。即可自动化转换为特定的 HTML 格式,直接复制粘贴到源代码里即可
音乐墙 + 音乐播放器 以及自动生成脚本 (Deprecated)
效果展示
实现专辑墙的效果,点击播放,进度条调整播放进度
前端代码
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 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <meta name ="viewport" content ="width=device-width, initial-scale=1.0" > <title > Music Playlist</title > <style > .music { width : 200px ; height : 200px ; border : 1px solid #ccc ; text-align : center; margin : 10px ; float : left; cursor : pointer; position : relative; transition : transform 0.3s ; } .music img { max-width : 100% ; max-height : 100% ; } .music :hover { transform : scale (1.1 ); } .music-info { position : absolute; top : 50% ; left : 50% ; transform : translate (-50% , -50% ); background : rgba (0 , 0 , 0 , 0.7 ); color : white; padding : 10px ; display : none; } .music :hover .music-info { display : block; } #playlist { display : flex; flex-wrap : wrap; justify-content : center; } #progress { width : 100% ; height : 10px ; border-radius : 5px ; background : linear-gradient (to right, #ff7e5f , #feb47b ); } input [type="range" ] { -webkit-appearance: none; appearance: none; } input [type="range" ] ::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width : 15px ; height : 15px ; border-radius : 50% ; background : #ff7e5f ; cursor : pointer; } #playPauseButton { background : #ff7e5f ; color : white; border : none; padding : 10px 20px ; border-radius : 5px ; cursor : pointer; } </style > </head > <body > <div id ="playlist" > <div class ="music" data-music ="https://ws6.stream.qqmusic.qq.com/C400002pSMav050h1b.m4a?guid=7104432948&vkey=B74730F1151F22AAEB27427BD0580BEE5B08953D4A30C7FB9F61785BA7AD3731F22483DD7319B802F32B11B2C19F236EC20ABA44170318E8&uin=1152921504695982864&fromtag=120032" > <img src ="https://y.qq.com/music/photo_new/T002R300x300M0000041GPv63o2YjS.jpg?max_age=2592000" alt ="Album Cover" > <div class ="music-info" > <h3 > Life Will Change<h3 > <p > 偷心的小曲</p > </div > </div > <div class ="music" data-music ="https://ws6.stream.qqmusic.qq.com/C400002HjpE82ZHxgP.m4a?guid=5402269082&vkey=14E912D5D8B2AFD36B8F9D6C6D13C446F273AFF5E8EDB9FF4D51B8D4F75FF2E7BF42CD04705076AF6861F6612E75CB7491AF6837B1C3849A&uin=1152921504695982864&fromtag=120032" > <img src ="https://y.qq.com/music/photo_new/T002R300x300M000001mmP543eChhy.jpg?max_age=2592000" alt ="Album Cover" > <div class ="music-info" > <h3 > Sogno di Volare<h3 > <p > 飞天梦</p > </div > </div > <div class ="music" data-music ="https://ws6.stream.qqmusic.qq.com/C4000029rUxI0mAMF1.m4a?guid=7779539200&vkey=182B987983B145090ABE2276E112C79D5EBF267B1DE606FA983381DB8F002AE5F80D746BC19EB1B16E4E1659830D4D93B90378B4C6E1A4ED&uin=1152921504695982864&fromtag=120032&src=C400002eIhPp1rMKw9.m4a" > <img src ="https://y.qq.com/music/photo_new/T002R300x300M000000AlbzG4DewiX.jpg?max_age=2592000" alt ="Album Cover" > <div class ="music-info" > <h3 > Tifa's Theme<h3 > <p > Tifa's Theme</p > </div > </div > <div class ="music" data-music ="https://api.liumingye.cn/m/api/link?id=d3f636iePH3nJMVUD1wHoQ2G0euQyv-U1R9WjW8zZeUIIj3mccA&quality=128&_t=1720351608093&token=20240531.2354a7d0ee396c5ff495bb89bfaa334f" > <img src ="https://y.qq.com/music/photo_new/T002R300x300M000002QETBK4JYkmb.jpg?max_age=2592000" alt ="Album Cover" > <div class ="music-info" > <h3 > The Wolven Storm<h3 > <p > The Wolven Storm</p > </div > </div > <div class ="music" data-music ="https://ws6.stream.qqmusic.qq.com/C400002Uob6p0hkBSb.m4a?guid=543775640&vkey=1C868FE1F472808CB646D3B65416DFA5B8BB5F97BDEBEC1CB740BAB5559808832C2312F174C60772CB9FB3BFEBD047D16A13BD6228C50EF7&uin=1152921504695982864&fromtag=120032" > <img src ="https://y.qq.com/music/photo_new/T002R300x300M000003E43vM1ZG6XB.jpg?max_age=2592000" alt ="Album Cover" > <div class ="music-info" > <h3 > Ezio's Family<h3 > <p > 刺客信条</p > </div > </div > <div class ="music" data-music ="https://ws6.stream.qqmusic.qq.com/C4000012S7kP4cT9fF.m4a?guid=5938620496&vkey=0B8BC643868950E58A120AD874A6C4A08117DEB31B4344F51192D7FE7405AA5EF7036FAAB235F2405139DE8BF2749AC2E1D416E193AF3BCF&uin=1152921504695982864&fromtag=120032" > <img src ="https://y.qq.com/music/photo_new/T002R300x300M000003kSOKf1RdYr8.jpg?max_age=2592000" alt ="Album Cover" > <div class ="music-info" > <h3 > Main Theme<h3 > <p > 钢铁雄心</p > </div > </div > <div class ="music" data-music ="https://ws6.stream.qqmusic.qq.com/C400003B5hh30XZz38.m4a?guid=7024553980&vkey=653752A81F7ADD154A3F95339D2ABC1B6B0AE5D877B2D7790BE21C9A25D3613F26F3D79781929EBFFA41DD1A92F4BD709339EADC7744F4EB&uin=1152921504695982864&fromtag=120032" > <img src ="https://y.qq.com/music/photo_new/T002R300x300M000000K79PQ1MPzdB_2.jpg?max_age=2592000" alt ="Album Cover" > <div class ="music-info" > <h3 > I Really Want to Stay at Your House<h3 > <p > Lucy…</p > </div > </div > <div class ="music" data-music ="https://ws6.stream.qqmusic.qq.com/C400002YWRfw1pH18h.m4a?guid=4599792750&vkey=6342535075BD87206289BF080A23E857323BAEFBDA86182B331D3B5535A8430A747CDA736C86F8E01C50DB6E25BF473811B3CD6D58AF50F1&uin=1152921504695982864&fromtag=120032" > <img src ="https://y.qq.com/music/photo_new/T002R300x300M000000zpV4e0Rpecf.jpg?max_age=2592000" alt ="Album Cover" > <div class ="music-info" > <h3 > Promise<h3 > <p > 寂静岭2</p > </div > </div > </div > <input type ="range" id ="progress" value ="0" step ="1" > <button id ="playPauseButton" > Play</button > <script > var audio = new Audio (); var progress = document .getElementById ("progress" ); var playPauseButton = document .getElementById ("playPauseButton" ); var musicList = document .querySelectorAll ('.music' ); musicList.forEach (function (music ) { music.addEventListener ("click" , function ( ) { audio.src = music.getAttribute ('data-music' ); audio.play (); playPauseButton.textContent = "Pause" ; }); }); progress.addEventListener ("input" , function ( ) { audio.currentTime = progress.value ; }); audio.addEventListener ("timeupdate" , function ( ) { progress.value = audio.currentTime ; }); audio.addEventListener ("canplay" , function ( ) { progress.max = audio.duration ; }); playPauseButton.addEventListener ("click" , function ( ) { if (audio.paused ) { audio.play (); playPauseButton.textContent = "Pause" ; } else { audio.pause (); playPauseButton.textContent = "Play" ; } }); </script > </body > </html >
可以实现一个专辑墙的效果,并且搭配有进度条和播放暂停按钮,可以实现音乐的播放。
python 自动生成脚本
musicWall.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 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 import pandas as pddf = pd.read_excel('music.xlsx' ) html_code = """ <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Music Playlist</title> <style> .music { width: 200px; height: 200px; border: 1px solid #ccc; text-align: center; margin: 10px; float: left; cursor: pointer; position: relative; transition: transform 0.3s; } .music img { max-width: 100%; max-height: 100%; } .music:hover { transform: scale(1.1); } .music-info { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); background: rgba(0, 0, 0, 0.7); color: white; padding: 10px; display: none; } .music:hover .music-info { display: block; } #playlist { display: flex; flex-wrap: wrap; justify-content: center; } #progress { width: 100%; height: 10px; border-radius: 5px; background: linear-gradient(to right, #ff7e5f, #feb47b); } input[type="range"] { -webkit-appearance: none; appearance: none; } input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 15px; height: 15px; border-radius: 50%; background: #ff7e5f; cursor: pointer; } #playPauseButton { background: #ff7e5f; color: white; border: none; padding: 10px 20px; border-radius: 5px; cursor: pointer; } </style> </head> <body> <div id="playlist"> """ for index, row in df.iterrows(): html_code += f""" <div class="music" data-music="{row['音乐url' ]} "> <img src="{row['专辑封面url' ]} " alt="Album Cover"> <div class="music-info"> <h3>{row['音乐名' ]} <h3> <p>{row['描述' ]} </p> </div> </div> """ html_code += """ </div> <input type="range" id="progress" value="0" step="1"> <button id="playPauseButton">Play</button> <script> var audio = new Audio(); var progress = document.getElementById("progress"); var playPauseButton = document.getElementById("playPauseButton"); var musicList = document.querySelectorAll('.music'); musicList.forEach(function(music) { music.addEventListener("click", function() { audio.src = music.getAttribute('data-music'); audio.play(); playPauseButton.textContent = "Pause"; }); }); progress.addEventListener("input", function() { audio.currentTime = progress.value; }); audio.addEventListener("timeupdate", function() { progress.value = audio.currentTime; }); audio.addEventListener("canplay", function() { progress.max = audio.duration; }); playPauseButton.addEventListener("click", function() { if (audio.paused) { audio.play(); playPauseButton.textContent = "Pause"; } else { audio.pause(); playPauseButton.textContent = "Play"; } }); </script> </body> </html> """ with open ('music_playlist.html' , 'w' , encoding='utf-8' ) as file: file.write(html_code) print ("Done!" )
直接把 Excel 表格中的数据读取出来,然后生成 HTML 代码,保存到文件中。
运行即可,直接得到完整的 HTML 文件。
这个功能有一个问题:在线音源比较难找,所以被废弃了(自己云储存对象的话太贵了
python 脚本: 替换图片链接
mdConvert.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import redef read_md_file (file_path ): with open (file_path, 'r' , encoding='utf-8' ) as file: return file.read() def replace_and_write (content, new_file_path ): new_content = re.sub(r'!\[\[([^]]+)\]\]' , r'<img src="ae490517/\1"/>' , content) with open (new_file_path, 'w' , encoding='utf-8' ) as file: file.write(new_content) def main (): md_file_path = r'......\blog1\source\_posts\课程笔记-ZJU-CTF101安全攻防实践.md' new_file_path = r'......\blog1\source\_posts\课程笔记-ZJU-CTF101安全攻防实践.md' content = read_md_file(md_file_path) replace_and_write(content, new_file_path) print ("Done!" ) if __name__ == "__main__" : main()
同样是解决 obsidian 图片引用格式无法被 hexo 正常识别的问题
obsidian 中原生的图片引用方式为
1 ![[Pasted image 20240521093347.png]]
该程序会自动进行正则匹配r'!\[\[([^]]+)\]\]'
会将其更换为 HTML 中的格式
1 2 <img src ="ae490517/\1" />
执行即可一键替换该 markdwon 文件中的所有图片引用格式