ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Python 解析“长得像 list 的 Document 字符串“:

2026/8/11 3:54:39 拓冰建站 浏览量
Python 解析“长得像 list 的 Document 字符串“:

Python 解析"长得像 list 的 Document 字符串":提取 page 并拼接(别再无脑 eval)

这是字符串转 list 系列的第 2 题。第 1 题里字符串是标准的 JSON / Python 列表,用json.loads/ast.literal_eval就能解决。

但这一题的字符串不是普通列表,而是一堆Document(...)——它是 LangChain 里Document对象的字符串表示(repr)

目标:取出每个 Document 的page(页码),并把每页的page_content(正文)拼接起来。

一、为什么第 1 题的方法在这里全部失效

这个字符串里既有单引号,又有Document(metadata=..., page_content=...)这种函数调用写法,它既不是 JSON,也不是 Python 字面量:

所以第 1 题那套在这里直接报废。

二、最稳的解法:正则提取(不碰 eval,最安全)

既然字符串格式是固定的Document(metadata={...}, page_content='...'),我们用正则只解析结构,不执行任何代码。这样无论来源是否可信都很安全。

思路:

  1. 用正则找出每一段Document(...),抓出它的metadata={...}page_content='...'
  1. 从 metadata 里取'page': 数字
  1. 把每段的page_content收集起来,按需拼接。

优点:纯正则、零执行、对任意来源都安全;不关心page_content里有什么奇怪字符,只认结构。

💡 小提示:如果原始字符串里的\n是"被转义过"的(\\n两个字符),提取出来的是字面量换行符。想要真正的换行,拼接前加一句:

三、拼接时想按"页码"排序怎么办

默认parse_documents是按字符串里出现的顺序返回的。如果你希望结果按page从小到大排:

四、如果你"完全掌控来源":用 eval 重建真实 Document

如果这段字符串确定是你自己代码print/repr出来的,绝对不会被外部篡改,也可以直接把它变回真正的Document对象,然后像平时一样用.metadata['page']访问:

⚠️为什么说"一般不推荐"eval执行字符串里的任意 Python 代码。一旦这段字符串来自用户、接口、数据库等外部输入,别人塞一句__import__('os').system('rm -rf /')就能造成破坏。而且page_content里的转义字符(\n)会被eval当成真换行解析,行为取决于字符串来源,不可控

五、正确的设计:别把 Document 存成 repr 字符串

Documentrepr只是给人看的调试输出,不是稳定的序列化格式。如果你要持久化或传输 Documents,请用 JSON / pickle:

这样以后无论是取page、拼正文,还是存数据库,都规规矩矩,不用再跟repr字符串斗智斗勇。

六、三种方式对比

方式

安全性

是否需可信来源

适用场景

正则提取(推荐)

只能拿到字符串、来源不可信或不想引依赖

eval重建 Document

低(代码注入)

你 100% 信任这段 repr 字符串、临时调试

JSON 序列化 / 反序列化

从设计上就该这么存/传,根本不该出现 repr 字符串

七、总结

  • 字符串里是Document(metadata=..., page_content=...)这种repr,不是 JSON / 字面量,json.loads/ast.literal_eval都救不了;
  • 首选正则提取:抓metadata里的'page'page_content,安全又稳;
  • 需要真实Document对象且来源可信时可用eval,但务必清楚它的注入风险;
  • 治本办法:从一开始就用json.dumps序列化 Document,而不是把repr当数据存。

一句话:拿 page、拼正文,用正则;想省事又安全,从源头改用 JSON。