[{"content":"","date":"18 November 2025","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","date":"18 November 2025","externalUrl":null,"permalink":"/tags/hugo/","section":"Tags","summary":"","title":"Hugo","type":"tags"},{"content":"**A Complete Workflow for “Hugo + GitHub + Two Branches (source/main) + Automatic Deployment”** Follow these steps and you’ll have everything running smoothly. Conventions:\nsource branch: Stores Hugo source code main branch: Stores the static files generated by Hugo (for GitHub Pages) I. Preparation 1. **Install Hugo** hugo version Install Hugo according to your operating system and verify the version. Create a GitHub Repository Create a new repo, for example: my-blog It comes with a default main branch, keep it (this will later store static files) II. Initialize Hugo Locally and Push to the `source` Branch 1. Clone the repository: git clone git@github.com:your-username/my-blog.git cd my-blog Create and switch to the source branch: git checkout -b source Initialize a Hugo project in the current directory: hugo new site . Add a theme (e.g., Ananke): git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke Add the following to config.toml:\ntheme = \u0026#34;ananke\u0026#34; baseURL = \u0026#34;https://your-username.github.io/\u0026#34; Create a test post: hugo new posts/hello-world.md Then edit content/posts/hello-world.md and change draft: true to false.\nCommit to the source branch: git add . git commit -m \u0026#34;init hugo site\u0026#34; git push origin source III. Make the `main` Branch Contain Only Static Files We let Hugo output to `public/` (default), and use GitHub Actions to sync `public` to the `main` branch. **You do not need to switch to the **`**main**`** branch manually.** GitHub requires two things:\nA GitHub Actions workflow (automatic build) GitHub Pages configuration (deploy from main) IV. Create a GitHub Actions Workflow Goal: When you push to the `source` branch: Automatically pull the code Install Hugo Run hugo to generate static files into public/ Push the content of public/ to the main branch Create the workflow folder inside the source branch: mkdir -p .github/workflows Create the file .github/workflows/gh-pages.yml with the following: name: GitHub Pages on: push: branches: - source # Trigger when source branch is updated jobs: build-deploy: runs-on: ubuntu-20.04 concurrency: group: ${{ github.workflow }}-${{ github.ref }} steps: - name: Checkout uses: actions/checkout@v3 with: submodules: true fetch-depth: 0 - name: Setup Hugo uses: peaceiris/actions-hugo@v2 with: hugo-version: \u0026#34;latest\u0026#34; - name: Build run: hugo --minify - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.HUGO_BLOG }} # Your GitHub token publish_branch: main # Push output to main branch publish_dir: ./public # Public directory is the Hugo output Commit the workflow: git add .github/workflows/gh-pages.yml git commit -m \u0026#34;add github actions for hugo deploy\u0026#34; git push origin source Go to your GitHub repo → Actions, and you should see the workflow running. If successful, the main branch will be created/updated with pure static files (index.html, etc.). V. Configure GitHub Pages to Use the `main` Branch 1. Go to your GitHub repo → **Settings** 2. Find **Pages** 3. Configure: - **Source**: `Deploy from a branch` - **Branch**: `main` → `/ (root)` 4. Save GitHub will give you a site URL, usually:\nhttps://your-username.github.io/\nor https://your-username.github.io/repo-name/ Your Hugo blog should appear in a few minutes.\nVI. Daily Blogging Workflow (Only Use the `source` Branch) 1. Ensure you're on the `source` branch: git checkout source Create a new post: hugo new posts/xxx.md Edit the file and change draft: true to false.\nLocal preview (optional): hugo server -D Visit http://localhost:1313 to preview.\nCommit and push: git add . git commit -m \u0026#34;add new post\u0026#34; git push origin source GitHub Actions will automatically build and deploy to main.\nGitHub Pages updates automatically.\nVII. Common Issues \u0026 Tips 1. **Incorrect baseURL** If your repository is notyour-username.github.io but a normal repo (e.g., my-blog),\nthen the baseURL in config.toml must be:\nbaseURL = \u0026#34;https://your-username.github.io/my-blog/\u0026#34; Do not edit the **main** branch manually It will be overwritten by every workflow run All content must be changed through the source branch only Actions Permissions The default GITHUB_TOKEN works for pushing to main If errors occur, go to:\nSettings → Actions → General → Workflow permissions\nand enable: Read and write permissions ","date":"18 November 2025","externalUrl":null,"permalink":"/en/posts/other/hugo_blog_tutorial/","section":"Posts","summary":"","title":"Hugo_Blog_Tutorial","type":"posts"},{"content":"一套「Hugo + GitHub + 两分支（source/main）+ 自动部署」的完整流程，你照着做就能跑起来。\n约定：\nsource 分支：Hugo 源码 main 分支：Hugo 生成的静态文件（给 GitHub Pages 用） 一、准备工作 1. **安装 Hugo** hugo version - 看你系统自己装就行，确认一下版本： GitHub 上建仓库 新建一个 repo，比如：my-blog 默认会有一个 main 分支，先保留（后面用来放静态文件） 二、本地初始化 Hugo 并推到 `source` 分支 1. 克隆仓库到本地： git clone git@github.com:你的用户名/my-blog.git cd my-blog 创建并切到 source 分支： git checkout -b source 在当前目录初始化 Hugo 项目（以 my-blog 为例）： hugo new site . 加主题（以 Ananke 为例）： git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke 在 config.toml 里加上：\ntheme = \u0026#34;ananke\u0026#34; baseURL = \u0026#34;https://你的用户名.github.io/\u0026#34; 随便新建一篇文章测试： hugo new posts/hello-world.md 然后去 content/posts/hello-world.md 把 draft: true 改成 false。\n提交到 source 分支： git add . git commit -m \u0026#34;init hugo site\u0026#34; git push origin source 三、让 `main` 分支只放静态文件 我们让 Hugo 的输出目录指向一个单独的目录（比如 `public/`，默认就是），再用 GitHub Actions 帮你把 `public` 的内容同步到 `main` 分支，**你本地不需要切 main 分支手动搞**。 GitHub 这边需要两件事：\nGitHub Actions workflow（自动构建） GitHub Pages 设置（从 main 分支部署） 四、创建 GitHub Actions 自动构建 \u003e 目标：当你 push 到 `source` 分支时： \u003e \u003e 1. 自动拉代码 \u003e 2. 安装 Hugo \u003e 3. 执行 `hugo` 生成静态文件到 `public/` \u003e 4. 把 `public/` 的内容推送到 `main` 分支 \u003e 在本地 source 分支创建 workflow 文件夹： mkdir -p .github/workflows 新建文件 .github/workflows/**\u0026lt;font style=\u0026quot;color:rgb(31, 35, 40);\u0026quot;\u0026gt;gh-pages\u0026lt;/font\u0026gt;**.yml，内容例如： name: GitHub Pages on: push: branches: - source # 当 source 分支有更新时触发构建 jobs: build-deploy: runs-on: ubuntu-20.04 concurrency: group: ${{ github.workflow }}-${{ github.ref }} steps: - name: Checkout uses: actions/checkout@v3 with: submodules: true fetch-depth: 0 - name: Setup Hugo uses: peaceiris/actions-hugo@v2 with: hugo-version: \u0026#34;latest\u0026#34; - name: Build run: hugo --minify - name: Deploy uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.HUGO_BLOG }} # 你的 GitHub token publish_branch: main # 将构建的内容推送到 main 分支 publish_dir: ./public # public 目录是 Hugo 构建后的输出目录 提交这个 workflow 文件： git add .github/workflows/gh-pages.yml git commit -m \u0026#34;add github actions for hugo deploy\u0026#34; git push origin source 这时候到 GitHub 仓库的 Actions 标签页里，应该会看到 workflow 在跑。 如果成功，main 分支会被自动创建/更新，里面就是纯静态文件（index.html 等）。 五、配置 GitHub Pages 使用 `main` 分支 1. 进入你的 GitHub 仓库页面 → Settings 2. 左侧找到 **Pages** 3. 配置： - **Source**：选 `Deploy from a branch` - **Branch**：选 `main` 分支，目录 `/ (root)` 4. 保存 GitHub 会给你一个地址，通常是：\nhttps://你的用户名.github.io/\n或 https://你的用户名.github.io/仓库名/ 几分钟后访问这个地址就能看到你的 Hugo 博客了。\n六、之后写博客的日常操作 以后你只需要动 **source 分支**： 确保在 source 分支： git checkout source 新建文章： hugo new posts/xxx.md 改好内容，把 draft: true 改成 false。\n本地预览（可选）： hugo server -D 浏览器访问 http://localhost:1313 看效果。\n提交并推送： git add . git commit -m \u0026#34;add new post\u0026#34; git push origin source GitHub Actions 会自动执行构建和部署，把更新后的静态文件推送到 main，GitHub Pages 自动更新。 七、常见坑 \u0026 建议 1. **baseURL 写错** - 如果你仓库名不是 `你的用户名.github.io`，而是普通仓库，例如 `my-blog`， 那 `config.toml` 里的 `baseURL` 应该是： baseURL = \u0026#34;https://你的用户名.github.io/my-blog/\u0026#34; main 分支手动改动会被覆盖 不要手动在 main 分支改任何东西，因为每次 workflow 部署都会覆盖。 所有内容都通过 source 分支的 Hugo 代码来维护。 Actions 权限 一般默认的 GITHUB_TOKEN 有权限推到 main，不用额外设置。 如果报权限错误，去仓库 → Settings → Actions → General\n确保 Workflow permissions 里勾选了： Read and write permissions ","date":"18 November 2025","externalUrl":null,"permalink":"/posts/other/hugo%E5%8D%9A%E5%AE%A2%E6%95%99%E7%A8%8B/","section":"Posts","summary":"","title":"Hugo博客教程","type":"posts"},{"content":"","date":"18 November 2025","externalUrl":null,"permalink":"/posts/","section":"Posts","summary":"","title":"Posts","type":"posts"},{"content":"","date":"18 November 2025","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":" 我是一名计算机专业, 具身智能方向的在读硕士研究生，\n以机械臂仿真开发、大模型高层任务规划为主，\n有时也会写下一些我的杂谈与随想。\n笔记主要在语雀平台记录，欢迎关注导航栏我的相关联系方式。\n你可以在 about me 了解更多关于我的信息。\n","date":"18 November 2025","externalUrl":null,"permalink":"/","section":"欢迎来到 Blowfish! 🎉","summary":"","title":"欢迎来到 Blowfish! 🎉","type":"page"},{"content":"","date":"18 November 2025","externalUrl":null,"permalink":"/categories/%E6%9D%82%E9%A1%B9/","section":"Categories","summary":"","title":"杂项","type":"categories"},{"content":"import urllib.request import gzip import io from lxml import etree import json import jsonpath # 1.获取网页源码 # 请求地址 url = \u0026#39;https://www.bilibili.com/video/BV1Es4y1q7Bf/?spm_id_from=333.788.comment.all.click\u0026amp;vd_source=3f0b4e269bbcd37b2419b130c0a77513\u0026#39; # 请求头 headers = { \u0026#39;User-Agent\u0026#39;: \u0026#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36\u0026#39;, \u0026#39;Referer\u0026#39;: \u0026#39;https://www.bilibili.com/\u0026#39;, \u0026#39;Accept\u0026#39;: \u0026#39;text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\u0026#39;, \u0026#39;Accept-Language\u0026#39;: \u0026#39;en-US,en;q=0.5\u0026#39;, \u0026#39;Connection\u0026#39;: \u0026#39;keep-alive\u0026#39;, \u0026#39;Upgrade-Insecure-Requests\u0026#39;: \u0026#39;1\u0026#39;, \u0026#39;TE\u0026#39;: \u0026#39;Trailers\u0026#39; } # 请求对象定制 request = urllib.request.Request(url=url, headers=headers) # 模拟浏览器向服务器发送请求 response = urllib.request.urlopen(request) # 读取响应的内容 content_bytes = response.read() # 从响应中读取的字节数据 # 响应内容是压缩的，需要解压，将压缩的字节数据解压并解码成UTF-8编码的字符串 content_io = io.BytesIO(content_bytes) # 创建了一个io.BytesIO对象，用于将字节数据包装成类似文件对象的形式 # 使用gzip.GzipFile来解压缩数据，mode=\u0026#39;rb\u0026#39;指定以二进制模式读取 with gzip.GzipFile(fileobj=content_io, mode=\u0026#39;rb\u0026#39;) as f: content = f.read().decode(\u0026#39;utf-8\u0026#39;) # # 将网页源码保存到文件“b站视频标题的获取（xpath）.html”中 with open(\u0026#39;b站视频标题的获取（xpath）.html\u0026#39;, \u0026#39;w\u0026#39;, encoding=\u0026#39;UTF-8\u0026#39;) as fp: fp.write(content) # 2.获取视频标题和时长 # （1）处理变成json数据 # 解析服务器响应的文件 etree.HTML tree = etree.HTML(content) # 获取想要的数据 the_data = tree.xpath(\u0026#39;/html/head[@itemprop=\u0026#34;video\u0026#34;]/script[5]/text()\u0026#39;)[0] # 由于tree.xpath返回的是列表，需要使用切片[0]将它取出来 the_json_data = the_data.split(\u0026#39;__=\u0026#39;)[1].split(\u0026#39;;(function\u0026#39;)[0] # （2）处理json数据，得到视频的标题和时长 # 使用jsonpath解析 video_data = json.loads(the_json_data) pages = video_data[\u0026#39;videoData\u0026#39;][\u0026#39;pages\u0026#39;] # 3. 定义一个转换秒数为分:秒格式的函数 def convert_seconds_to_minutes_seconds_format(seconds): minutes = seconds // 60 seconds = seconds % 60 return f\u0026#34;{minutes:02}:{seconds:02}\u0026#34; # 4. 打印每个视频的标题和时长，并累加总时长 total_duration_seconds = 0 # 用于累加总时长 for page in pages: title = page[\u0026#39;part\u0026#39;] # 获取视频的标题 duration = page[\u0026#39;duration\u0026#39;] # 获取视频的时长（单位为秒） # 转换时长为分:秒格式 formatted_duration = convert_seconds_to_minutes_seconds_format(duration) # 打印每个视频的时长 print(f\u0026#34;标题: {title}, 时长: {formatted_duration}\u0026#34;) #print(formatted_duration) # 累加时长 total_duration_seconds += duration def convert_seconds_to_time_format(seconds): # 计算小时 hours = seconds // 3600 # 计算分钟 minutes = (seconds % 3600) // 60 # 计算剩余秒数 seconds = seconds % 60 # 返回格式化的字符串，确保小时、分钟、秒都是两位数 return f\u0026#34;{hours:02}:{minutes:02}:{seconds:02}\u0026#34; # 5. 计算总时长并转换为时:分:秒格式 total_formatted_duration = convert_seconds_to_time_format(total_duration_seconds) print(f\u0026#34;\\n所有视频的总时长: {total_formatted_duration}\u0026#34;) ","date":"1 March 2025","externalUrl":null,"permalink":"/en/posts/other/crawl-the-duration-and-title-of-bilibili-videos/","section":"Posts","summary":"","title":"Crawl the duration and title of Bilibili videos","type":"posts"},{"content":"","date":"1 March 2025","externalUrl":null,"permalink":"/en/categories/other/","section":"Categories","summary":"","title":"Other","type":"categories"},{"content":"","date":"1 March 2025","externalUrl":null,"permalink":"/en/tags/spider/","section":"Tags","summary":"","title":"Spider","type":"tags"},{"content":"","date":"1 March 2025","externalUrl":null,"permalink":"/tags/%E7%88%AC%E8%99%AB/","section":"Tags","summary":"","title":"爬虫","type":"tags"},{"content":" 代码 # import urllib.request import gzip import io from lxml import etree import json import jsonpath # 1.获取网页源码 # 请求地址 url = \u0026#39;https://www.bilibili.com/video/BV1Es4y1q7Bf/?spm_id_from=333.788.comment.all.click\u0026amp;vd_source=3f0b4e269bbcd37b2419b130c0a77513\u0026#39; # 请求头 headers = { \u0026#39;User-Agent\u0026#39;: \u0026#39;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36\u0026#39;, \u0026#39;Referer\u0026#39;: \u0026#39;https://www.bilibili.com/\u0026#39;, \u0026#39;Accept\u0026#39;: \u0026#39;text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\u0026#39;, \u0026#39;Accept-Language\u0026#39;: \u0026#39;en-US,en;q=0.5\u0026#39;, \u0026#39;Connection\u0026#39;: \u0026#39;keep-alive\u0026#39;, \u0026#39;Upgrade-Insecure-Requests\u0026#39;: \u0026#39;1\u0026#39;, \u0026#39;TE\u0026#39;: \u0026#39;Trailers\u0026#39; } # 请求对象定制 request = urllib.request.Request(url=url, headers=headers) # 模拟浏览器向服务器发送请求 response = urllib.request.urlopen(request) # 读取响应的内容 content_bytes = response.read() # 从响应中读取的字节数据 # 响应内容是压缩的，需要解压，将压缩的字节数据解压并解码成UTF-8编码的字符串 content_io = io.BytesIO(content_bytes) # 创建了一个io.BytesIO对象，用于将字节数据包装成类似文件对象的形式 # 使用gzip.GzipFile来解压缩数据，mode=\u0026#39;rb\u0026#39;指定以二进制模式读取 with gzip.GzipFile(fileobj=content_io, mode=\u0026#39;rb\u0026#39;) as f: content = f.read().decode(\u0026#39;utf-8\u0026#39;) # # 将网页源码保存到文件“b站视频标题的获取（xpath）.html”中 with open(\u0026#39;b站视频标题的获取（xpath）.html\u0026#39;, \u0026#39;w\u0026#39;, encoding=\u0026#39;UTF-8\u0026#39;) as fp: fp.write(content) # 2.获取视频标题和时长 # （1）处理变成json数据 # 解析服务器响应的文件 etree.HTML tree = etree.HTML(content) # 获取想要的数据 the_data = tree.xpath(\u0026#39;/html/head[@itemprop=\u0026#34;video\u0026#34;]/script[5]/text()\u0026#39;)[0] # 由于tree.xpath返回的是列表，需要使用切片[0]将它取出来 the_json_data = the_data.split(\u0026#39;__=\u0026#39;)[1].split(\u0026#39;;(function\u0026#39;)[0] # （2）处理json数据，得到视频的标题和时长 # 使用jsonpath解析 video_data = json.loads(the_json_data) pages = video_data[\u0026#39;videoData\u0026#39;][\u0026#39;pages\u0026#39;] # 3. 定义一个转换秒数为分:秒格式的函数 def convert_seconds_to_minutes_seconds_format(seconds): minutes = seconds // 60 seconds = seconds % 60 return f\u0026#34;{minutes:02}:{seconds:02}\u0026#34; # 4. 打印每个视频的标题和时长，并累加总时长 total_duration_seconds = 0 # 用于累加总时长 for page in pages: title = page[\u0026#39;part\u0026#39;] # 获取视频的标题 duration = page[\u0026#39;duration\u0026#39;] # 获取视频的时长（单位为秒） # 转换时长为分:秒格式 formatted_duration = convert_seconds_to_minutes_seconds_format(duration) # 打印每个视频的时长 print(f\u0026#34;标题: {title}, 时长: {formatted_duration}\u0026#34;) #print(formatted_duration) # 累加时长 total_duration_seconds += duration def convert_seconds_to_time_format(seconds): # 计算小时 hours = seconds // 3600 # 计算分钟 minutes = (seconds % 3600) // 60 # 计算剩余秒数 seconds = seconds % 60 # 返回格式化的字符串，确保小时、分钟、秒都是两位数 return f\u0026#34;{hours:02}:{minutes:02}:{seconds:02}\u0026#34; # 5. 计算总时长并转换为时:分:秒格式 total_formatted_duration = convert_seconds_to_time_format(total_duration_seconds) print(f\u0026#34;\\n所有视频的总时长: {total_formatted_duration}\u0026#34;) ","date":"1 March 2025","externalUrl":null,"permalink":"/posts/other/%E7%88%AC%E5%8F%96%E5%93%94%E5%93%A9%E5%93%94%E5%93%A9%E8%A7%86%E9%A2%91%E6%97%B6%E9%95%BF%E5%92%8C%E6%A0%87%E9%A2%98/","section":"Posts","summary":"","title":"爬取哔哩哔哩视频时长和标题","type":"posts"},{"content":"你好！我是一名计算机专业, 具身智能方向的在读硕士研究生， 以机械臂仿真开发、大模型高层任务规划为主， 有时也会写下一些我的杂谈与随想。 笔记主要在语雀平台记录，欢迎关注导航栏我的相关联系方式。\n欢迎与我联系，我的个人邮箱是: misdazzling01@gmail.com 经历和项目 # voxPoser复现 2024-07 voxPoser 解决官方仓库部署的bug：VoxPoser: Composable 3D Value Maps for Robotic Manipulation with Language Models 微信公众号接入chatgpt 2023-09 chatgpt-wechat 为你的微信公众号接入chatgpt，免服务器 开源项目 # misDazzling/VoxPoser 复现VoxPoser HTML 20 3 misDazzling/chatgpt-wechat 为你的微信公众号接入chatgpt，免服务器，只需APIkey。 JavaScript 11 3 ","externalUrl":null,"permalink":"/about/","section":"欢迎来到 Blowfish! 🎉","summary":"","title":"About Me","type":"page"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"}]