
从字符串中提取 Document 的 page_content手动拆还是用工具背景继上一题的手拆字符串之后又来了一个升级版字符串内容如下为了阅读方便我做了换行处理“[Document(metadata{‘pk’: 12, ‘page’: 2}, page_content‘这里是第一段正文内容…’), Document(metadata{‘pk’: 27, ‘page’: 2}, page_content‘这里是第二段正文内容…’), Document(metadata{‘pk’: 14, ‘page’: 3}, page_content‘这里是第三段正文内容…’)]”需求是从这个字符串中提取每个 Document 的 page_content正文内容然后拼接成一个完整的字符串。这道题的核心考点是给定一个包含对象的字符串如何安全地提取其中的特定字段page_content。思路一纯手动拆分正则表达式既然字符串有固定格式Document(metadata{‘pk’: 数字, ‘page’: 数字}, page_content‘这里是正文…’)我们可以直接用正则表达式提取 page_content 后面的内容import re raw_str [Document(metadata{pk: 12, page: 2}, page_content这里是第一段正文内容...), Document(metadata{pk: 27, page: 2}, page_content这里是第二段正文内容...), Document(metadata{pk: 14, page: 3}, page_content这里是第三段正文内容...)] # 提取 page_content 后面的内容 contents re.findall(rpage_content(.*?), raw_str) # 拼接成完整字符串 result .join(contents) print(result) # 输出: 这里是第一段正文内容...这里是第二段正文内容...这里是第三段正文内容...优点代码短思路直接不需要额外库re 是标准库缺点极其脆弱如果正文里包含单引号正则就会失效不通用换一种对象结构就得重写正则如果 page_content 的值包含换行或特殊字符代码立刻报错思路二用 ast.literal_eval 解析更安全如果我们能把字符串转成 Python 对象然后直接访问 page_content 属性那就安全得多。但问题来了ast.literal_eval 不认识 Document 这个类名所以不能直接解析。解决思路把 Document(…) 替换成字典 {…}import re import ast raw_str [Document(metadata{pk: 12, page: 2}, page_content这里是第一段正文内容...), Document(metadata{pk: 27, page: 2}, page_content这里是第二段正文内容...), Document(metadata{pk: 14, page: 3}, page_content这里是第三段正文内容...)] # 提取 metadata 和 page_content pattern rDocument\(metadata({.*?}), page_content(.*?)\) matches re.findall(pattern, raw_str) contents [] for metadata_str, content in matches: contents.append(content) # content 就是 page_content 的值 result .join(contents) print(result) # 输出: 这里是第一段正文内容...这里是第二段正文内容...这里是第三段正文内容...优点解析的是 Python 字面量安全可靠能处理稍微复杂的格式变化只要 metadata 部分合法缺点代码比纯正则稍复杂如果 page_content 里有单引号仍然会出问题思路三针对 page_content 包含特殊字符的终极方案如果 page_content 里面可能包含单引号、换行等特殊字符上面的正则就失效了。这时候需要更精确的匹配策略import re import ast raw_str [Document(metadata{pk: 12, page: 2}, page_content第一段正文...), Document(metadata{pk: 27, page: 2}, page_content第二段正文...)] # 用正则提取 metadata 部分再单独提取 page_content pattern rDocument\(metadata({.*?}), page_content(.*?)\) matches re.findall(pattern, raw_str) contents [] for metadata_str, content in matches: # 如果 content 里有转义字符用 ast.literal_eval 安全还原 try: # 把 content 当作 Python 字符串字面量解析 safe_content ast.literal_eval(f{content}) contents.append(safe_content) except: contents.append(content) result .join(contents)思路四如果题目给的是对象列表最理想情况如果题目不是给你一个字符串而是给你一个已经存在的 documents 列表那就直接操作对象即可contents [doc.page_content for doc in documents] result .join(contents)这是最简单、最直接、最安全的方式。这道题在考试中的正确答法如果题目明确说这是一个字符串用 ast.literal_eval 配合 re.findall 提取 page_content 字段然后拼接。如果题目说有一个 documents 列表直接用列表推导式 [doc.page_content for doc in documents]。如果 page_content 可能包含特殊字符如引号、换行用 ast.literal_eval 做二次安全解析。总结一句话手动拆分是能做到但正确做法是安全解析。考试看的是你对工具的理解不是你折腾字符串的能力。三种方式对比方式代码量安全性通用性推荐度纯正则手拆短极低极低不推荐ast.literal_eval 正则中高中推荐直接操作对象列表短极高极高最推荐彩蛋如果 page_content 包含换行或特殊字符怎么办如果正文内容可能包含换行或特殊字符上面的方法仍然可以处理因为 ast.literal_eval 能安全解析 Python 字符串字面量。但如果正文内容非常长或者包含各种特殊符号最稳妥的方式是在字符串生成时就做好序列化而不是在解析时临时处理。