可以爬取K-工作门户吗?

힘센캥거루
2025년 5월 28일(수정됨)
48
python

最近看到K-工作门户将公文标题按3个月的单位显示后,我产生了这样的想法。

如果通过爬虫将所有公文标题整理成3年期的Excel文件呢?

通过filter可以轻松搜索公文编号。

我先下结论,不可能

可以爬取K-工作门户吗?-1

1. 每个人都有计划。

我的宏伟计划是这样的。

1. 使用 python 的 selenium 访问工作门户并登录。
2. 使用 xpath 收集 table 标签内部的 tr 和 td,并将其制成数据帧。
3. 使用 datetime 和 delta 计算日期,将公文按3个月单位收集齐全。
4. 使用 Excel 或 Google 表格合理利用。

但是实际进入工作门户时,连 table 都找不到,iframe更是找不到。

折腾了4小时后,我记录下爬虫不可能的原因。

2. 你的安全在哪里?

1. WebDRM

可以爬取K-工作门户吗?-2

第一个障碍是 WebDRM。

这导致无法开启开发者模式。

不过利用开发者模式已经开启的情况下,即使访问该网站也能保持的方法,成功开启了开发者模式。

2. 浏览器可见但没有元素?

这部分最难以理解。

明明开发者模式下元素清晰可见,但在 Chrome 驱动中执行 page_source 时没有任何元素。

无论使用 selenium 还是 puppeteer,结果都是一样。

更神奇的是,即使在控制台使用 JavaScript 也看不到。

看得到却找不到,这种似是而非的情况让我更加发疯。

const puppeteer = require('puppeteer');
const fs = require('fs');
// 使用 puppeteer 获取网页 HTML 的脚本

(async () => {
  let browser;
  try {
    browser = await puppeteer.launch({
      headless: false,
      args: ['--no-sandbox', '--disable-setuid-sandbox'],
      defaultViewport: null,
      userDataDir: './user_data',
    });

    const page = await browser.newPage();

    await page.goto('https://klef.goe.go.kr/keris_ui/main.do', {
      waitUntil: 'networkidle0', // 等待所有资源加载
      timeout: 60000, // 最长等待60秒
    });

    const html = await page.content();
    fs.writeFileSync('schoolDoc.html', html, 'utf8');
    console.log('HTML 文件已保存为 schoolDoc.html。');

  } catch (error) {
    console.error('发生错误:', error);
  } finally {
    if (browser) await browser.close();
  }
})();

这样保存的文件再次打开时显示如下。

想要的表格没有出现,登录模块倒是弹出来了。

可以爬取K-工作门户吗?-3

思考为什么会这样,觉得公文显示的表格本身可能并不是其他安装类型的程序。

这样想来放弃就容易多了。

3. 工作门户使用 WebSocket。

首先,工作门户不是通过常规的 REST API 传送数据,而是使用 websocket 与用户进行数据交换。

这一点非常有趣。

可以爬取K-工作门户吗?-4

因此,即使尝试使用 requests 等库复制 cookie 进行新连接,因 websocket 的握手过程和会话保持方式,仍然无法实现。

但我不愿在此放弃。

于是决定通过 selenium-wire 查看通过 websocket 进行的请求和响应。

# 循环请求
for request in driver.requests:
    if request.response:
        content_type = request.response.headers.get('Content-Type', '')
        if content_type.startswith('application/json'):
            print("== 请求 URL:", request.url)
            try:
                body = request.response.body.decode('utf-8', errors='ignore')
                print("== 响应内容:", body)
            except Exception as e:
                print("== 解码错误:", e)

driver.quit()

结果得到似乎是 base64 编码的字母。

尝试解码,但因不符合规范而失败。

到此我决定停下来。

3. 感想

对公共机构网站的速度缓慢不满,但这次尝试后觉得至少安全做得很好。

获得远程数据并不容易,通过此经历学到了不少。

不过,下次可能还会再试。

可以爬取K-工作门户吗?-5

댓글을 불러오는 중...