Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 41 additions & 14 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,23 @@ jobs:
if-no-files-found: error

docker:
name: Docker ${{ matrix.platform }}
name: Docker ${{ matrix.variant }} ${{ matrix.platform }}
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- platform: amd64
- variant: with-browser
platform: amd64
runner: ubuntu-latest
- platform: arm64
- variant: with-browser
platform: arm64
runner: ubuntu-24.04-arm
- variant: without-browser
platform: amd64
runner: ubuntu-latest
- variant: without-browser
platform: arm64
runner: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v6
Expand All @@ -87,19 +95,21 @@ jobs:
id: build
with:
context: .
file: Dockerfile
target: ${{ matrix.variant }}
platforms: linux/${{ matrix.platform }}
outputs: type=image,push-by-digest=true,name=${{ secrets.DOCKERHUB_USERNAME }}/weban,push=true
provenance: false
cache-from: type=gha,scope=${{ matrix.platform }}
cache-to: type=gha,scope=${{ matrix.platform }},mode=max
cache-from: type=gha,scope=docker-${{ matrix.platform }}
cache-to: type=gha,scope=docker-${{ matrix.platform }},mode=max

- name: Export digest
run: echo "${{ steps.build.outputs.digest }}" > digest-${{ matrix.platform }}.txt
run: echo "${{ steps.build.outputs.digest }}" > digest-${{ matrix.variant }}-${{ matrix.platform }}.txt

- uses: actions/upload-artifact@v7
with:
name: digest-${{ matrix.platform }}
path: digest-${{ matrix.platform }}.txt
name: digest-${{ matrix.variant }}-${{ matrix.platform }}
path: digest-${{ matrix.variant }}-${{ matrix.platform }}.txt

docker-merge:
name: Docker merge
Expand All @@ -120,27 +130,44 @@ jobs:
merge-multiple: true

- uses: docker/metadata-action@v6
id: meta
id: meta-with-browser
with:
images: ${{ secrets.DOCKERHUB_USERNAME }}/weban
tags: |
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=raw,value=latest
type=raw,value=with-browser

- uses: docker/metadata-action@v6
id: meta-without-browser
with:
images: ${{ secrets.DOCKERHUB_USERNAME }}/weban
tags: |
type=semver,pattern={{version}}-without-browser
type=raw,value=without-browser

- name: Merge with-browser manifests
run: |
img="${{ secrets.DOCKERHUB_USERNAME }}/weban"
docker buildx imagetools create \
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "${{ steps.meta-with-browser.outputs.json }}") \
"$img@$(cat digests/digest-with-browser-amd64.txt)" \
"$img@$(cat digests/digest-with-browser-arm64.txt)"

- name: Merge multi-platform manifests
- name: Merge without-browser manifests
run: |
img="${{ secrets.DOCKERHUB_USERNAME }}/weban"
docker buildx imagetools create \
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
"$img@$(cat digests/digest-amd64.txt)" \
"$img@$(cat digests/digest-arm64.txt)"
$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "${{ steps.meta-without-browser.outputs.json }}") \
"$img@$(cat digests/digest-without-browser-amd64.txt)" \
"$img@$(cat digests/digest-without-browser-arm64.txt)"

release:
name: Release
permissions:
contents: write
needs: [build, docker-merge]
needs: [build, docker, docker-merge]
if: startsWith(github.ref, 'refs/tags/')
runs-on: ubuntu-latest
steps:
Expand Down
31 changes: 21 additions & 10 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
# WeBan Docker 镜像
# 目标:
# with-browser — 内置浏览器,开箱即用
# without-browser — 通过 CDP 连接宿主机浏览器

# ── Builder: PyInstaller 打包 ──────────────────────────────
FROM python:3.12-slim-bookworm AS builder
FROM python:3.12-slim AS builder

COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
RUN apt-get update && apt-get install -y --no-install-recommends binutils \
&& rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir uv

WORKDIR /build

Expand All @@ -25,20 +30,26 @@ RUN --mount=type=cache,target=/root/.cache/uv \
--hidden-import numpy \
--hidden-import cv2 \
--collect-submodules nodriver \
main.py
main.py \
&& strip /build/dist/WeBan

# ── with-browser: 内置 Chrome headless shell ───────────────
FROM chromedp/headless-shell:stable AS with-browser

COPY --from=builder /build/dist/WeBan /app/WeBan
WORKDIR /app

ENV CHROMIUM_BINARY=/headless-shell/headless-shell
ENV WEBAN_NO_SANDBOX=1

# ── Runtime ────────────────────────────────────────────────
FROM debian:bookworm-slim
ENTRYPOINT ["/app/WeBan"]

RUN apt-get update && apt-get install -y --no-install-recommends --no-install-suggests \
chromium \
&& rm -rf /var/lib/apt/lists/* /var/cache/apt/* /tmp/* \
&& mkdir -p /app/logs
# ── without-browser: 纯二进制,CDP 连接宿主机浏览器 ────────
FROM debian:stable-slim AS without-browser

COPY --from=builder /build/dist/WeBan /app/WeBan
WORKDIR /app

ENV CHROMIUM_BINARY=/usr/bin/chromium
ENV WEBAN_NO_SANDBOX=1

ENTRYPOINT ["/app/WeBan"]
54 changes: 52 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,19 +49,69 @@ python main.py # 或 uv run main.py

### Docker

**完整镜像**(内置 Chromium,开箱即用):
提供两种镜像变体:

| 镜像 | Tag | 说明 |
|------|-----|------|
| 内置浏览器 | `latest` / `with-browser` / `<版本号>` | 开箱即用 |
| 轻量镜像 | `without-browser` / `<版本号>-without-browser` | 通过 CDP 连接宿主机浏览器 |

#### 完整镜像(内置浏览器)

```bash
docker run -it --rm \
-v "$PWD/config.toml":/app/config.toml:ro \
-v "$PWD/logs":/app/logs \
hangyi/weban:latest
```

#### 轻量镜像(CDP 连接宿主机浏览器)

容器会自动检测 Docker 环境并尝试连接宿主机的 Chrome,无需手动配置 CDP。

**第一步:在宿主机启动 Chrome 远程调试**

打开 Chrome,地址栏输入 `chrome://inspect/#remote-debugging`,勾选 **Allow remote debugging for this browser instance**。

或者直接命令行启动带远程调试的 Chrome:

```bash
# macOS
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" --remote-debugging-port=9222

# Linux
google-chrome --remote-debugging-port=9222

# Windows
"C:\Program Files\Google\Chrome\Application\chrome.exe" --remote-debugging-port=9222
```

> 参考:[Chrome DevTools: Debug your browser session](https://developer.chrome.com/blog/chrome-devtools-mcp-debug-your-browser-session)

**第二步:运行容器**

```bash
docker run -it --rm \
-v "$PWD/config.toml":/app/config.toml:ro \
-v "$PWD/logs":/app/logs \
hangyi/weban
hangyi/weban:without-browser
```

如需自定义 CDP 地址,可在 `config.toml` 中配置 `cdp_host` 和 `cdp_port`。

## 配置说明

首次使用先从 [config.example.toml](config.example.toml) 复制一份 `config.toml` 并填写账号信息。账号级配置可覆盖全局设置。

### 浏览器检测

程序按以下优先级自动检测可用的浏览器,无需手动配置:

1. **用户指定**:环境变量 `CHROMIUM_BINARY` / 配置文件 `browser_path`
2. **CDP 远程调试**:配置文件 `cdp_host` + `cdp_port`,或 Docker 环境下自动尝试 `host.docker.internal:9222`
3. **Playwright 浏览器**:`pip install playwright && playwright install chromium`
4. **系统浏览器**:自动查找已安装的 Chrome / Chromium

## 功能特性

- **课程学习**:自动遍历项目 → 分类 → 课程,模拟翻页、答题、等待学习时长后完课
Expand Down
84 changes: 84 additions & 0 deletions answer/answer.json
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,19 @@
],
"type": 1
},
"In China, how many types of fire are there?": {
"optionList": [
{
"content": "Six.",
"isCorrect": 1
},
{
"content": "Four.",
"isCorrect": 2
}
],
"type": 1
},
"In addition to the explosion, how often does it take to control the fire after a fire?": {
"optionList": [
{
Expand Down Expand Up @@ -3672,6 +3685,19 @@
],
"type": 1
},
"一个心地善良的人会以为别人都是善良的;一个经常算计别人的人就会觉得别人也在算计他,这就是心理学上说的:": {
"optionList": [
{
"content": "投射效应",
"isCorrect": 1
},
{
"content": "羊群效应",
"isCorrect": 2
}
],
"type": 1
},
"一个有同理心的人,一般具有哪些品质?": {
"optionList": [
{
Expand Down Expand Up @@ -32028,6 +32054,10 @@
{
"content": "积极心态。",
"isCorrect": 1
},
{
"content": "消极心态。",
"isCorrect": 2
}
],
"type": 1
Expand Down Expand Up @@ -33589,6 +33619,27 @@
],
"type": 1
},
"常被骗的人,可能存在的共同特征之一是?": {
"optionList": [
{
"content": "尊重他人",
"isCorrect": 2
},
{
"content": "容易被小便宜吸引",
"isCorrect": 1
},
{
"content": "不轻易转账",
"isCorrect": 2
},
{
"content": "警惕性强",
"isCorrect": 2
}
],
"type": 1
},
"常见的地震前兆不包括哪个?": {
"optionList": [
{
Expand Down Expand Up @@ -37465,6 +37516,10 @@
{
"content": "立即接听",
"isCorrect": 1
},
{
"content": "骗子太多,赶快挂掉",
"isCorrect": 2
}
],
"type": 1
Expand Down Expand Up @@ -37943,6 +37998,10 @@
{
"content": "对",
"isCorrect": 1
},
{
"content": "错",
"isCorrect": 2
}
],
"type": 1
Expand Down Expand Up @@ -39170,6 +39229,18 @@
{
"content": "努力带着溺水者游向安全地带。",
"isCorrect": 2
},
{
"content": "放手自沉,使溺水者手松开,再进行救护",
"isCorrect": 1
},
{
"content": "努力带着溺水者游向安全地带",
"isCorrect": 2
},
{
"content": "强行掰开对方手臂拉扯",
"isCorrect": 2
}
],
"type": 1
Expand Down Expand Up @@ -48220,6 +48291,19 @@
],
"type": 1
},
"破窗理论是谁提出的?": {
"optionList": [
{
"content": "詹姆士·威尔逊和乔治·凯林",
"isCorrect": 1
},
{
"content": "詹姆士·威尔逊",
"isCorrect": 2
}
],
"type": 1
},
"确定是流感或疑似流感并有并发症时,最好在多长时间内进行治疗?": {
"optionList": [
{
Expand Down
Loading
Loading