Beautiful Soup 如何解码 <script> 对象中的 html json 数据

Posted

技术标签:

【中文标题】Beautiful Soup 如何解码 <script> 对象中的 html json 数据【英文标题】:Beautiful Soup how to decode html json data in <script> object 【发布时间】:2020-09-19 11:00:04 【问题描述】:

我从发布简短新闻更新的网站收集文本。最近该网站的前端进行了升级,现在使用 Angular。历史文档加载到新 Angular“新闻”页面的元素中。

此脚本元素中的数据是以 html 格式存储为 JSON。它以我不熟悉的格式编码。我一直无法解码它。但是,Chrome 浏览器会解释元素中的元素。

从存储每个旧文档的元素中提取如下所示:

 <script id="ng-agritown-state" type="application/json">

&q;G.api_endpoint/api/v12/pages?parameters=newsId%3D343436565656&a;path=news-article&q;:&q;body&q;:&q;id&q;:&q;8&q;,&q;layout&q;:&q;onecol&q;,&q;info&q;:&q;title&q;:&q;News article&q;

    ... 

    &q;&g;&l;span class=\&q;z\&q;&g;Record harvest 2020&l;/span&g;&l;/p&g;\n&l;p class=\&q;a\&q;&g;&l;span class=\&q;z\&q;&g;We are pleased to announce a record harvest in this current

    ...

    &q;isDataComponentAndIsAvailable&q;:true,&q;status&q;:&q;refreshedTime&q;:1590993288947,&q;childComponents&q;:[],&q;params&q;:&q;updates&q;:null,&q;cloneFrom&q;:null,&q;encoder&q;:,&q;map&q;:null]

</script>

任何人都可以识别这种编码格式吗?如何使用 Python / Beautiful Soup 对其进行解码?

【问题讨论】:

如果您有一个指向包含这种编码类型的在线页面的链接,也许可以多说一些。就目前而言,它看起来像是 HTML 实体的某种简写(即 &amp;q; 而不是 &amp;quote;),但目前尚不清楚在没有上下文的情况下如何甚至为什么会起作用。你说你是从一个网站上得到这个的,也许分享一个链接? 文档示例如下页所示。我对实际新闻的缩进部分感兴趣。 londonstockexchange.com/news-article/RGD/… 脚本 id 中的 "ng- 已经暴露了一点:编码是 Angular 对 html 的自定义编码。由于您关注的是整篇文章的内容,因此无法进行简单的搜索和替换——您需要找到一种方法让 Angular 为您解码。最简单的方法可能是让 Python 加载支持 javascript 的引擎,并简单地让它呈现您在浏览器中看到的 html,然后使用 Python 访问生成的文档,就像使用 Selenium 或 PyV8 一样。不过,这些都是繁重的解决方案,如果您需要频繁或轻微地运行此脚本,请不要使用它们。 【参考方案1】:

与我的评论一致:脚本 id 中的 "ng- 已经泄露了它:编码是 Angular 对 HTML 的自定义编码。由于您关注的是整篇文章的内容,因此无法进行简单的搜索和替换——您需要找到一种方法让 Angular 为您解码。

最简单的方法可能是让 Python 加载一个支持 JavaScript 的引擎,让它渲染出您在浏览器中看到的 HTML,然后使用 Python 访问生成的文档,例如使用 Selenium 或 PyV8。不过,这些都是繁重的解决方案,如果您需要频繁运行此脚本或使用少量资源,请不要使用它们。

以下代码使用 Selenium,通过以下方式准备您的虚拟环境:

安装硒pip install selenium 安装适当的浏览器驱动程序,在本例中为 ChromeDriver,从此处:https://sites.google.com/a/chromium.org/chromedriver/home(我只是将可执行文件放在我的脚本文件夹中,在 Windows 上)

运行这个:

from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://www.londonstockexchange.com/news-article/RGD/year-end-trading-and-covid-19-update/14495760")
elem = driver.find_element_by_class_name('news-article-content-body')
print(elem.text)

当然,只要您也获得了驱动程序,您也可以让它与其他支持的浏览器一起使用。它在其他操作系统上的工作方式类似。

如果您确实需要经常运行,有办法让 Selenium 在服务器上运行以更快地创建会话并重复呈现页面,但这远远超出了 *** 的单一答案。

【讨论】:

【参考方案2】:

此内容似乎是自定义编码的。你可以试试简单的str.replace

txt = r'''<script id="ng-agritown-state" type="application/json">

&q;G.api_endpoint/api/v12/pages?parameters=newsId%3D343436565656&a;path=news-article&q;:&q;body&q;:&q;id&q;:&q;8&q;,&q;layout&q;:&q;onecol&q;,&q;info&q;:&q;title&q;:&q;News article&q;

    ...

    &q;&g;&l;span class=\&q;z\&q;&g;Record harvest 2020&l;/span&g;&l;/p&g;\n&l;p class=\&q;a\&q;&g;&l;span class=\&q;z\&q;&g;We are pleased to announce a record harvest in this current

    ...

    &q;isDataComponentAndIsAvailable&q;:true,&q;status&q;:&q;refreshedTime&q;:1590993288947,&q;childComponents&q;:[],&q;params&q;:&q;updates&q;:null,&q;cloneFrom&q;:null,&q;encoder&q;:,&q;map&q;:null]

</script>'''


from bs4 import BeautifulSoup

soup = BeautifulSoup(txt, 'html.parser')

print( soup.script.contents[0].replace('&l;', '<').replace('&g;', '>').replace('&q;', '"') )

打印:

"G.api_endpoint/api/v12/pages?parameters=newsId%3D343436565656&a;path=news-article":"body":"id":"8","layout":"onecol","info":"title":"News article"

    ...

    "><span class=\"z\">Record harvest 2020</span></p>\n<p class=\"a\"><span class=\"z\">We are pleased to announce a record harvest in this current

    ...

    "isDataComponentAndIsAvailable":true,"status":"refreshedTime":1590993288947,"childComponents":[],"params":"updates":null,"cloneFrom":null,"encoder":,"map":null]

然后json/re模块对信息进行解码。

【讨论】:

这种工作。数据太脏,无法将其转换回 JSON 对象,但它为数据提供了足够的结构来使用正则表达式提取 html。谢谢。

以上是关于Beautiful Soup 如何解码 <script> 对象中的 html json 数据的主要内容,如果未能解决你的问题,请参考以下文章

hdu4872 Beautiful Soup 模拟

如何使用 Beautiful Soup 从 <script> 中提取内容

如何通过 Beautiful Soup 刮掉href中的文本?

如何使用 Beautiful Soup 提取此 HTML 元素属性的值?

Beautiful Soup 笔记 1基本使用

用 Beautiful Soup 解析 HTML 中的 Data-Bind 标签