爬取 Luogu

369天前 · 技术 · 运维 · 1037次阅读

 爬取 Luogu

Luogu 是国内知名的学习网站,为方便学习,现期望爬取其题目数据供本地学习。

 技术分析

Luogu 采用的既不是前后端分离,也不是完全的服务端渲染,而是一种将两者结合的技术路线。传回的页面会有一个基本的内容用作没有 JS 的 fallback,而终端版本将会用 Vue 进行渲染。然而,这些数据并不是单独请求,而是服务端已经将数据编码为 JSON 并注入到页面当中。从页面注释,这个基本的 fallback 的主要目的是搜索引擎优化。

返回的页面

 爬取数据

Luogu 限制了没有 UA 的请求,因此需要在请求中附带 UA。同时,对请求频率有所限制,需要在请求间进行等待。

页面注入的数据信息

爬取后,使用正则表达式获取注入的 JSON。

result = re.search(r'JSON\.parse\(decodeURIComponent\("(.*)"\)\)', response.text)

 寻找标签

爬取得到的数据中,有一个tags。不难理解,返回的数字指的是标签对应的序号。但是,这个标签的hashmap在哪里呢?寻找所有请求,都没有发现有关tag的请求;查询所有资源,包括JS,原本的标签文本甚至是Unicode都无法找到对应的字符串。难不成 Luogu采用了量子通信?

仔细思考后,可能是Luogu在首次请求后将相关数据缓存。LocalStorage 和 SessionStorage 都较小,因此 IndexedDB 是最有可能的。果不其然,相关数据存储于名为lfeData数据库的luoguTags项目下。删除这个数据库再次请求,可以发现请求标签字符串的请求,这个请求附带了一个时间戳作为查询值(时间飞逝,时间戳竟然已经以17开头了)。

存于 IndexedDB 的标签信息

删除 DB 后,可以看到请求

 关键代码

import requests
import re
from urllib.parse import unquote
import json

from datetime import datetime

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"
}

now = datetime.now()
timestamp = datetime.timestamp(now)
response = requests.get(
    "https://www.luogu.com.cn/_lfe/tags?_version=%f" % timestamp, headers=headers
)
tags = json.loads(response.text)["tags"]
tags = {i["id"]: i["name"] for i in tags}

infos = []
retry = 0

for i in range(1000, 9868):
    response = requests.get("https://www.luogu.com.cn/problem/P%d" % i, headers=headers)

    result = re.search(r'JSON\.parse\(decodeURIComponent\("(.*)"\)\)', response.text)
    content = result.group(1)
    content = unquote(content)
    data = json.loads(content)

    problem = data["currentData"]["problem"]
    infos.append(problem)


with open("luogu.json", "w") as fp:
    json.dump(infos, fp, indent=4, ensure_ascii=False)
👍 4

洛谷 爬虫

最后修改于341天前

评论

贴吧 狗头 原神 小黄脸
收起

贴吧

  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡
  • 贴吧泡泡

狗头

  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头
  • 狗头

原神

  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神
  • 原神

小黄脸

  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸
  • 小黄脸

目录

avatar

老班长

炼欲望为永恒

9

文章数

0

评论数

12

分类