You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从101围棋网提取围棋题并转换为SGF格式?

从101围棋网站抓取题目并转换为SGF格式的方案

核心思路:直接解析qqdata变量(最优方案)

网站页面末尾<script>标签里的qqdata变量就是题目数据的源头,完全不需要从canvas做视觉提取,你提到的第三方Python项目也是基于这个变量解析,并非视觉识别。

步骤1:提取页面中的qqdata

  • Python环境:用requests拉取页面源码,再通过正则表达式匹配var qqdata = (.+?);提取JSON格式的题目数据;
  • TypeScript(Node.js环境):用axios获取页面内容,配合正则或cheerio定位目标script标签后提取变量内容。

步骤2:自定义坐标转SGF坐标

101围棋的自定义坐标以棋盘左上角为原点,SGF坐标规则为列用a-o(15路)/a-s(19路),行用1-15/19,且先列后行,转换逻辑:

  • 101的x值对应SGF的列:将数字转为小写字母(x=0→a,x=1→b,以此类推);
  • 101的y值对应SGF的行:因101的y=0是棋盘最上方,SGF的行1是最下方,需反转计算(如19路棋盘,SGF行号=19 - y)。

步骤3:生成标准SGF格式

SGF基础结构为(;GM[1]FF[4]SZ[19];B[aa];W[ab]...),其中:

  • GM[1]标记为围棋,FF[4]指定SGF版本,SZ[19]对应棋盘大小(根据题目实际调整);
  • 遍历qqdata中的黑白棋子位置,分别用B[坐标]和W[坐标]追加到SGF结构中,空棋盘仅保留头部即可。

具体实现示例

Python版本

import requests
import re
import json

def fetch_qqdata(url: str):
    response = requests.get(url)
    match = re.search(r'var qqdata = (.+?);', response.text, re.DOTALL)
    if not match:
        raise ValueError("未找到qqdata变量")
    return json.loads(match.group(1))

def convert_to_sgf(qqdata):
    board_size = qqdata.get('size', 19)
    sgf_parts = [f'(;GM[1]FF[4]SZ[{board_size}]']
    
    # 处理黑棋
    for stone in qqdata.get('black', []):
        x, y = stone['x'], stone['y']
        col = chr(ord('a') + x)
        row = str(board_size - y)
        sgf_parts.append(f';B[{col}{row}]')
    
    # 处理白棋
    for stone in qqdata.get('white', []):
        x, y = stone['x'], stone['y']
        col = chr(ord('a') + x)
        row = str(board_size - y)
        sgf_parts.append(f';W[{col}{row}]')
    
    sgf_parts.append(')')
    return ''.join(sgf_parts)

# 使用示例
if __name__ == '__main__':
    target_url = "目标题目链接"
    qqdata = fetch_qqdata(target_url)
    sgf_content = convert_to_sgf(qqdata)
    print(sgf_content)

TypeScript(Node.js)版本

import axios from 'axios';

async function fetchQQData(url: string) {
    const response = await axios.get(url);
    const match = response.data.match(/var qqdata = (.+?);/s);
    if (!match) {
        throw new Error('未找到qqdata变量');
    }
    return JSON.parse(match[1]);
}

function convertToSGF(qqdata: any): string {
    const boardSize = qqdata.size || 19;
    const sgfParts: string[] = [`(;GM[1]FF[4]SZ[${boardSize}]`];

    // 处理黑棋
    qqdata.black?.forEach((stone: {x: number, y: number}) => {
        const col = String.fromCharCode('a'.charCodeAt(0) + stone.x);
        const row = boardSize - stone.y;
        sgfParts.push(`;B[${col}${row}]`);
    });

    // 处理白棋
    qqdata.white?.forEach((stone: {x: number, y: number}) => {
        const col = String.fromCharCode('a'.charCodeAt(0) + stone.x);
        const row = boardSize - stone.y;
        sgfParts.push(`;W[${col}${row}]`);
    });

    sgfParts.push(')');
    return sgfParts.join('');
}

// 使用示例
(async () => {
    const targetUrl = "目标题目链接";
    const qqdata = await fetchQQData(targetUrl);
    const sgfContent = convertToSGF(qqdata);
    console.log(sgfContent);
})();

注意事项

  • 部分页面需登录访问,此时需在请求中携带登录后的Cookie(Python用requests.Session(),TS用axios的headers配置);
  • 若qqdata结构发生变动,需根据实际返回的JSON调整解析逻辑;
  • 遵守网站规则,避免高频请求导致IP被封禁。

内容的提问来源于stack exchange,提问作者psygo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 15:17:13