VPS 搭建文件抓取系统(2)

一、先确认当前文件还在旧目录

在修改脚本之前,先确认现在的文件还没有按年、月分开。

执行:

find /srv/policybot/data/ndrc/raw_html -maxdepth 1 -type f | head
find /srv/policybot/data/ndrc/text -maxdepth 1 -type f | head

正常情况下,会看到类似:

/srv/policybot/data/ndrc/raw_html/2026-02-13_9dc84789f0.html
/srv/policybot/data/ndrc/raw_html/2026-02-12_xxxxx.html
/srv/policybot/data/ndrc/text/2026-02-13_9dc84789f0.txt
/srv/policybot/data/ndrc/text/2026-02-12_xxxxx.txt

这说明:

  • html 文件都直接堆在 raw_html/ 根目录
  • txt 文件都直接堆在 text/ 根目录

这样短期可以用,长期不适合。

如果以后文件变成几千、几万、几十万:

  • 很难找
  • 很难备份
  • 很难检查某个月的数据
  • 很难补抓某一段时间

所以目标就是:

把数据按 年 / 月 归档。

最终结构要变成:

/srv/policybot/data/ndrc
├── index
│   ├── policy_index.csv
│   └── url_index.txt
├── meta
├── raw_html
│   ├── 2024
│   │   ├── 03
│   │   ├── 04
│   │   └── ...
│   ├── 2025
│   │   ├── 01
│   │   └── ...
│   └── 2026
│       ├── 01
│       └── 02
└── text
    ├── 2024
    │   ├── 03
    │   ├── 04
    │   └── ...
    ├── 2025
    │   ├── 01
    │   └── ...
    └── 2026
        ├── 01
        └── 02

二、先创建新的归档目录

先把将来要用的目录建出来。

执行:

mkdir -p /srv/policybot/data/ndrc/raw_html
mkdir -p /srv/policybot/data/ndrc/text
mkdir -p /srv/policybot/data/ndrc/meta
mkdir -p /srv/policybot/data/ndrc/index

这一步不会删除旧文件,也不会影响已有数据。

接着手动创建一个测试月份目录,确认结构没有问题:

mkdir -p /srv/policybot/data/ndrc/raw_html/2026/02
mkdir -p /srv/policybot/data/ndrc/text/2026/02

查看结构:

tree -L 3 /srv/policybot/data/ndrc

正常会看到类似:

/srv/policybot/data/ndrc
├── index
├── meta
├── raw_html
│   └── 2026
│       └── 02
└── text
    └── 2026
        └── 02

这一步只是确认目录结构可用。
后面不会只用 2026/02,而是根据文件日期自动分到不同年份、月份。


三、先不要手工一个个建年份和月份

当前已有文件不是只有 2026/02,而是覆盖多个时间。

例如已经抓到的文件,可能包含:

  • 2024 年
  • 2025 年
  • 2026 年

而且每年有多个不同月份。

所以不能靠手工这样建:

mkdir -p /srv/policybot/data/ndrc/raw_html/2024/03
mkdir -p /srv/policybot/data/ndrc/raw_html/2024/04
mkdir -p /srv/policybot/data/ndrc/raw_html/2024/05
...

这样太慢,也容易漏。

正确做法是:

根据文件名前缀自动建目录,再自动移动文件。

文件名本身已经带日期,例如:

2026-02-13_9dc84789f0.html
2025-11-05_xxxxx.txt
2024-03-18_xxxxx.html

这些文件名前半段已经包含:

YYYY-MM-DD

所以只要把年份和月份从文件名里切出来,就能自动归档。


四、先整理 html 文件

执行下面这段脚本,不要改。

python - <<'PY'
import os
import shutil

base = "/srv/policybot/data/ndrc/raw_html"

for name in os.listdir(base):
    path = os.path.join(base, name)

    if not os.path.isfile(path):
        continue

    if not name.endswith(".html"):
        continue

    parts = name.split("_", 1)
    if len(parts) < 2:
        continue

    date = parts[0]

    if len(date) != 10 or date[4] != "-" or date[7] != "-":
        continue

    year = date[:4]
    month = date[5:7]

    target_dir = os.path.join(base, year, month)
    os.makedirs(target_dir, exist_ok=True)

    shutil.move(path, os.path.join(target_dir, name))
    print("moved", name, "->", f"{year}/{month}")
PY

这段脚本做了什么

它会:

  1. 扫描 raw_html/ 根目录下所有文件
  2. 找到扩展名是 .html 的文件
  3. 从文件名前缀中取出日期
  4. 年 / 月 自动创建目录
  5. 把文件移动进去

例如:

2026-02-13_9dc84789f0.html

会移动到:

/srv/policybot/data/ndrc/raw_html/2026/02/2026-02-13_9dc84789f0.html

五、再整理 txt 文件

执行下面这段脚本,不要改。

python - <<'PY'
import os
import shutil

base = "/srv/policybot/data/ndrc/text"

for name in os.listdir(base):
    path = os.path.join(base, name)

    if not os.path.isfile(path):
        continue

    if not name.endswith(".txt"):
        continue

    parts = name.split("_", 1)
    if len(parts) < 2:
        continue

    date = parts[0]

    if len(date) != 10 or date[4] != "-" or date[7] != "-":
        continue

    year = date[:4]
    month = date[5:7]

    target_dir = os.path.join(base, year, month)
    os.makedirs(target_dir, exist_ok=True)

    shutil.move(path, os.path.join(target_dir, name))
    print("moved", name, "->", f"{year}/{month}")
PY

这段脚本做了什么

逻辑和 html 那段完全一样,只不过这次处理的是 txt 文件。

例如:

2025-11-05_xxxxx.txt

会移动到:

/srv/policybot/data/ndrc/text/2025/11/2025-11-05_xxxxx.txt

这样 html 和 txt 的目录层级就一致了。


六、检查归档结果

执行:

tree -L 4 /srv/policybot/data/ndrc

正常会看到类似:

/srv/policybot/data/ndrc
├── index
│   ├── policy_index.csv
│   └── url_index.txt
├── meta
├── raw_html
│   ├── 2024
│   │   ├── 03
│   │   ├── 04
│   │   ├── ...
│   ├── 2025
│   │   ├── 01
│   │   ├── 02
│   │   ├── ...
│   └── 2026
│       ├── 01
│       └── 02
└── text
    ├── 2024
    │   ├── 03
    │   ├── 04
    │   ├── ...
    ├── 2025
    │   ├── 01
    │   ├── 02
    │   ├── ...
    └── 2026
        ├── 01
        └── 02

如果能看到这种结构,说明旧文件已经成功按年月归档。


七、检查文件数量有没有丢

归档前后,文件总数不应该变化。

执行:

find /srv/policybot/data/ndrc/raw_html -type f -name "*.html" | wc -l
find /srv/policybot/data/ndrc/text -type f -name "*.txt" | wc -l
wc -l /srv/policybot/data/ndrc/index/policy_index.csv
wc -l /srv/policybot/data/ndrc/index/url_index.txt

正常情况下,这几个数字应该接近。

例如:

556
556
556
556

如果归档后 html 或 txt 文件数量明显少了,说明移动过程有问题。
这种情况下不要继续改脚本,先排查目录。


八、为什么索引文件不用改

当前 policy_index.csv 里保存的是:

标题,日期,原始链接,html文件名,txt文件名

这里记录的是 文件名,不是完整路径。

例如:

关于加强投资项目在线审批监管平台和工程建设项目审批管理系统数据共享的通知,2026-02-13,https://www.ndrc.gov.cn/...,2026-02-13_9dc84789f0.html,2026-02-13_9dc84789f0.txt

因为它没有写死旧路径,所以归档以后不需要修改 CSV。

真正变化的只是文件在磁盘中的目录位置:

  • 以前在 raw_html/
  • 现在在 raw_html/YYYY/MM/

文件名本身没有变,所以索引仍然有效。

九、修改爬虫脚本,让新数据自动进入年月目录

现在旧文件已经归档,但如果继续使用原来的 ndrc.py,新抓的数据仍然会落在:

/srv/policybot/data/ndrc/raw_html
/srv/policybot/data/ndrc/text

因此需要修改脚本,让它在保存文件时 自动创建年份 / 月份目录

先打开脚本:

nano /srv/policybot/crawler/ndrc.py

找到函数 fetch_page,原来的代码类似:

html_file = f"{date}_{file_hash}.html"
txt_file = f"{date}_{file_hash}.txt"

html_path = os.path.join(HTML_DIR, html_file)
txt_path = os.path.join(TEXT_DIR, txt_file)

把这一段替换为:

year = date[:4]
month = date[5:7]

html_dir = os.path.join(HTML_DIR, year, month)
txt_dir = os.path.join(TEXT_DIR, year, month)

os.makedirs(html_dir, exist_ok=True)
os.makedirs(txt_dir, exist_ok=True)

html_file = f"{date}_{file_hash}.html"
txt_file = f"{date}_{file_hash}.txt"

html_path = os.path.join(html_dir, html_file)
txt_path = os.path.join(txt_dir, txt_file)

保存并退出:

Ctrl + O
Enter
Ctrl + X

十、重新运行爬虫测试

执行:

cd /srv/policybot/crawler
python ndrc.py

如果抓到新的政策页面,会看到类似输出:

page: 1
saved: 关于推进能源领域数字化发展的通知
saved: 关于促进区域产业发展的意见

十一、确认新文件进入年月目录

查看最新文件:

ls -lt /srv/policybot/data/ndrc/raw_html/2026/02 | head

示例输出:

-rw-r--r-- 1 root root 24512 Feb 13 2026-02-13_9dc84789f0.html
-rw-r--r-- 1 root root 21401 Feb 12 2026-02-12_xxxxx.html

再查看 txt:

ls -lt /srv/policybot/data/ndrc/text/2026/02 | head

示例输出:

-rw-r--r-- 1 root root 19844 Feb 13 2026-02-13_9dc84789f0.txt
-rw-r--r-- 1 root root 17501 Feb 12 2026-02-12_xxxxx.txt

说明新数据已经自动进入对应月份。


十二、检查爬虫是否仍然正确去重

再次运行:

python ndrc.py

如果页面已经抓过,会看到:

skip: 关于加强投资项目在线审批监管平台和工程建设项目审批管理系统数据共享的通知

说明:

  • url_index.txt 仍然在工作
  • 脚本不会重复抓取同一页面

十三、检查文件数量是否一致

执行:

find /srv/policybot/data/ndrc/raw_html -type f -name "*.html" | wc -l
find /srv/policybot/data/ndrc/text -type f -name "*.txt" | wc -l
wc -l /srv/policybot/data/ndrc/index/policy_index.csv
wc -l /srv/policybot/data/ndrc/index/url_index.txt

正常情况下,这几个数字应该接近。

例如:

556
556
556
556

如果一致,说明:

  • 归档没有丢数据
  • 新抓取逻辑正常
  • 索引没有损坏

十四、完成状态

完成后,数据目录应变成:

/srv/policybot/data/ndrc
├── index
│   ├── policy_index.csv
│   └── url_index.txt
├── meta
├── raw_html
│   ├── 2024
│   │   ├── 03
│   │   ├── 04
│   │   └── ...
│   ├── 2025
│   │   ├── 01
│   │   └── ...
│   └── 2026
│       ├── 01
│       └── 02
└── text
    ├── 2024
    │   ├── 03
    │   ├── 04
    │   └── ...
    ├── 2025
    │   ├── 01
    │   └── ...
    └── 2026
        ├── 01
        └── 02

并且:

  • 旧数据已经归档
  • 新数据自动进入对应年月目录
  • 索引文件仍然正常工作
  • 爬虫可以持续运行