【问题标题】:How to extract content from <script> using Beautiful Soup如何使用 Beautiful Soup 从 <script> 中提取内容
【发布时间】:2020-05-04 18:37:34
【问题描述】:

我正在尝试从此处脚本标签中的代码中提取campaign_hearts 和postal_code(整个代码太长,无法发布):

<script>
...    
"campaign_hearts":4817,"social_share_total":11242,"social_share_last_update":"2020-01-17T10:51:22-06:00","location":{"city":"Los Angeles, CA","country":"US","postal_code":"90012"},"is_partner":false,"partner":{},"is_team":true,"team":{"name":"Team STEVENS NATION","team_pic_url":"https://d2g8igdw686xgo.cloudfront.net
...

我可以使用以下代码识别我需要的脚本:

from bs4 import BeautifulSoup
import numpy as np
import pandas as pd
from time import sleep
import requests 
import re
import json


page = requests.get("https://www.gofundme.com/f/eric-stevens-care-trust")

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

all_scripts = soup.find_all('script')
all_scripts[0]

但是,我不知道如何提取我想要的值。 (我对 Python 很陌生。) This thread 为类似问题推荐了以下解决方案(经过编辑以反映我正在使用的 html)。

data = json.loads(all_scripts[0].get_text()[27:])

但是,运行它会产生错误:JSONDecodeError: Expecting value: line 1 column 1 (char 0).

既然我已经识别了正确的脚本,我可以做些什么来提取我需要的值?我也尝试过here 列出的解决方案,但在导入 Parser 时遇到了问题。

【问题讨论】:

    标签: python html json python-3.x beautifulsoup


    【解决方案1】:

    您可以使用json 模块解析&lt;script&gt; 的内容,然后获取您的值。例如:

    import re
    import json
    import requests
    
    url = 'https://www.gofundme.com/f/eric-stevens-care-trust'
    
    txt = requests.get(url).text
    
    data = json.loads(re.findall(r'window\.initialState = ({.*?});', txt)[0])
    
    # print( json.dumps(data, indent=4) )  # <-- uncomment this to see all data
    
    print('Campaign Hearts =', data['feed']['campaign']['campaign_hearts'])
    print('Postal Code     =', data['feed']['campaign']['location']['postal_code'])
    

    打印:

    Campaign Hearts = 4817
    Postal Code     = 90012
    

    【讨论】:

    • 从来不知道这种加载 JSON 的方式。惊人的! :)
    • re.findall()[0] 不只是re.search()
    • @AMC 可以写成re.search(r'window\.initialState = ({.*?});', txt).group(1)re.search(..)[1]。这只是口味问题。
    • 只是口味问题。只是有点,因为.findall()会得到每一个匹配项,不管它是否被丢弃。
    【解决方案2】:

    你使用的库越多;代码效率越低!这是一个更简单的解决方案-

    #This imports the website content.
    
    import requests
    url = "https://www.gofundme.com/f/eric-stevens-care-trust"
    a = requests.post(url)
    a= (a.content)
    print(a)
    
    #These will show your data.
    
    campaign_hearts = str(a,'utf-8').split('campaign_hearts":')[1]
    campaign_hearts = campaign_hearts.split(',"social_share_total"')[0]
    print(campaign_hearts)
    
    postal_code = str(a,'utf-8').split('postal_code":"')[1]
    postal_code = postal_code.split('"},"is_partner')[0]
    print(postal_code)   
    

    【讨论】:

    • 只是补充一点:我不会说代码变得不那么“高效”,因为在谈论效率时通常暗示 speed 效率,这里不是这样。但它会变得不那么直截了当,因为它增加了理解更多不同库的需要。
    • 是的。我的意思是当工作可以用时间石完成时,你不需要整个无限手套哈哈 :)
    • 确实如此 :)
    • 我很好奇,你为什么使用 POST 请求?
    • 说到效率,如果 OP 想要整个 JSON 内容怎么办?
    【解决方案3】:

    您的json.loads 因最后一个分号而失败。如果您使用正则表达式仅提取对象字符串(不包括最后的分号),它将起作用。

    from bs4 import BeautifulSoup
    import numpy as np
    import pandas as pd
    from time import sleep
    import requests 
    import re
    import json
    
    
    
    page = requests.get("https://www.gofundme.com/f/eric-stevens-care-trust")
    
    soup = BeautifulSoup(page.content, 'html.parser')
    
    all_scripts = soup.find_all('script')
    txt = all_scripts[0].get_text()
    data = json.loads(re.findall(r'window\.initialState = ({.*?});', txt)[0])
    

    【讨论】:

      【解决方案4】:

      现在应该没问题,我可能会尝试编写一个纯 lxml 版本或至少改进元素的搜索。

      此解决方案使用正则表达式仅获取 JSON 数据,不使用 window.initialState = 和分号。

      import json
      import re
      
      import requests
      from bs4 import BeautifulSoup
      
      url_1 = "https://www.gofundme.com/f/eric-stevens-care-trust"
      
      req = requests.get(url_1)
      
      soup = BeautifulSoup(req.content, 'lxml')
      
      script_tag = soup.find('script')
      
      raw_json = re.fullmatch(r"window\.initialState = (.+);", script_tag.text).group(1)
      
      json_content = json.loads(raw_json)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-12-04
        • 2017-12-31
        • 1970-01-01
        • 1970-01-01
        • 2016-11-27
        • 1970-01-01
        • 2021-02-22
        • 1970-01-01
        相关资源
        最近更新 更多