为了账号安全,请及时绑定邮箱和手机立即绑定

使用 Beautiful Soup 从特定脚本标签中查找嵌套的 JS 对象值

使用 Beautiful Soup 从特定脚本标签中查找嵌套的 JS 对象值

蛊毒传说 2022-05-22 10:31:58
我正在用漂亮的汤抓取一个网站来抓取图像,到目前为止,这对每个网站都很好,我什至设法创建了一些自定义案例类型。但是一个特定的站点给我带来了问题,因为它返回了一个 JavaScript 对象中的所有图像,该对象内嵌在一个脚本标记中。该对象非常大,因为它包含所有产品信息,我正在寻找的特定位嵌套在 productArticleDetails > [产品 id] > normalImages > thumbnail > [图像路径] 中。像这样:<script>var productArticleDetails = {   ...   '0399310001': {      ...      'normalImages': [         {            'thumbnail': '//image-path.jpg',            ...         }      ]   }}     所以我只想提取图像路径。它也不是返回的“汤”中包含在脚本标记中的唯一内容,代码中还有许多其他 javascript 标记。到目前为止,我已将 HTML 保存到一个变量中,然后运行:soup = BeautifulSoup(html)scripts = soup.find_all('script')所以我留下了一个包含所有<script>元素的对象html不知何故,在该scripts对象中,我需要在正确的 JS 块中找到该特定节点并返回thumbnail嵌套在该节点下的normalImages节点的值,该节点又将嵌套在一串数字下方,最终全部保存到productArticleDetailsvar .我想我需要对对象进行for循环,scripts但没有运气弄清楚如何提取特定的数据位。我所看到的其他所有内容都假设只有 1 位 javaScript 并且您要查找的值不是嵌套的。任何人都可以帮忙吗?干杯。
查看完整描述

2 回答

?
芜湖不芜

TA贡献1796条经验 获得超7个赞

如果您可以做一个简化的假设,例如,您要解析的对象}与行首的最终齐平,这很容易:


import ast

import re

from bs4 import BeautifulSoup


html = """

<script>

// we don't care about this script tag

</script>


<script>

var productArticleDetails = {

   '0399310001': {

      'normalImages': [

         {

            'thumbnail': '//image-path.jpg',

         }

      ]

   }

}


var someOtherThing = 42;

</script>

"""


soup = BeautifulSoup(html, "lxml")


for script in soup.find_all("script"):

    pattern = r"^var productArticleDetails = (.+?^})"


    if m := re.search(pattern, script.text, re.M | re.S):

        data = ast.literal_eval(m.group(1))

        break


print(data["0399310001"]["normalImages"][0]["thumbnail"])

输出:


//image-path.jpg

但是,如果你不能做出这个假设,也许你可以做出不同的假设,比如“把所有东西都拿起来,直到下一个空行作为对象”:


pattern = r"^var productArticleDetails = (.+?^\s*$)"

如果这仍然太脆弱并且对象可能是任何形式,那么我们就会遇到正则表达式不适合的平衡括号检测问题。您可以使用堆栈来确定对象何时结束(如果数据包含}内部字符串,请小心,但这是一个可导航的解析问题)。


请注意,ast.literal_eval()如果 JS 对象的键周围没有引号,则会失败,因此您可能还需要为这种情况做一些准备。目前尚不清楚这是否是您需要的静态一次性解析,或者您是否正在寻找可以承受任何 JS 对象格式的强大解决方案。


json.loads在这里非常没用,因为它假定 JSON 格式完美。JS 对象几乎从不采用这种形式,如此处所示。


查看完整回答
反对 回复 2022-05-22
?
慕尼黑的夜晚无繁华

TA贡献1864条经验 获得超6个赞

import json

from bs4 import BeautifulSoup


html = """<script type="application/ld+json">

var productArticleDetails = {

                    "@context" : "https://schema.org",

                    "@type" : "BreadcrumbList",

                    "itemListElement": [ {"@type":"ListItem","thumbnail":"//image-path.jpg","item":{"@id":"https://www.myntra.com/","name":"Home"}},{"@type":"ListItem","position":2,"item":{"@id":"https://www.myntra.com/clothing","name":"Clothing"}},{"@type":"ListItem","position":3,"item":{"@id":"https://www.myntra.com/men-clothing","name":"Men Clothing"}},{"@type":"ListItem","position":4,"item":{"@id":"https://www.myntra.com/shirts","name":"Shirts"}},{"@type":"ListItem","position":5,"item":{"@id":"https://www.myntra.com/formal-shirts-for-men","name":"Formal Shirts For Men"}} ]

                }

            </script>"""


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


sc = soup.find("script").text


data = sc.split("=", 1)[1]



ld = json.loads(data)


# print(json.dumps(ld, indent=4))


print(ld["itemListElement"][0]["thumbnail"])

输出:


//image-path.jpg


查看完整回答
反对 回复 2022-05-22
  • 2 回答
  • 0 关注
  • 348 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信