[{"content":"","date":"18 November 2025","externalUrl":null,"permalink":"/en/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","date":"18 November 2025","externalUrl":null,"permalink":"/en/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":"/en/posts/","section":"Posts","summary":"","title":"Posts","type":"posts"},{"content":"","date":"18 November 2025","externalUrl":null,"permalink":"/en/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"18 November 2025","externalUrl":null,"permalink":"/en/categories/%E6%9D%82%E9%A1%B9/","section":"Categories","summary":"","title":"杂项","type":"categories"},{"content":" I am a master\u0026rsquo;s student majoring in Computer Science, specializing in Embodied Intelligence.\nMy focus is on robotic arm simulation development and large models high-level task planning for robot.\nSometimes, I also write down my thoughts and musings.\nMy notes are mainly recorded on the Yuque platform. Feel free to check out my contact information in the navigation bar.\nYou can learn more about me in the \u0026ldquo;About Me\u0026rdquo; section.\n","date":"18 November 2025","externalUrl":null,"permalink":"/en/","section":"欢迎来到 Blowfish ！","summary":"","title":"欢迎来到 Blowfish ！","type":"page"},{"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":" 代码 # 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":"","date":"1 March 2025","externalUrl":null,"permalink":"/tags/%E7%88%AC%E8%99%AB/","section":"Tags","summary":"","title":"爬虫","type":"tags"},{"content":"Hello! I am a master\u0026rsquo;s student majoring in Computer Science, specializing in Embodied Intelligence. My main focus is on robotic arm simulation development and high-level task planning for large models. Sometimes, I also write some of my thoughts and musings. I mainly record my notes on the Yuque platform. Feel free to follow my contact information in the navigation bar.\nFeel free to contact me and my email is : 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":"/en/about/","section":"欢迎来到 Blowfish ！","summary":"","title":"About Me","type":"page"},{"content":"","externalUrl":null,"permalink":"/en/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/en/series/","section":"Series","summary":"","title":"Series","type":"series"}]