首页 文章

Python - 如何从脚本中的变量内部提取数据?

提问于
浏览
1

我是Python的新手,我正在尝试使用BeautifulSoup从脚本中定义的变量中提取一些数据 .

data = soup.find_all('script', type='text/javascript')
print(data[0])

<script type="text/javascript">
  var myvar = {
    productid: "101",
    productname: "Abc",
  };
</script>

您是否知道从myvar变量中提取'productid'和'productname'的简单方法?

3 回答

  • 0

    解析

    from bs4 import BeautifulSoup
    
    script_data='''
    <script type="text/javascript">
      var myvar = {
        productid: "101",
        productname: "Abc",
      };
    </script>
    '''
    soup = BeautifulSoup(script_data)
    

    soup.script.stringscript 标记内的数据保存为字符串 . 您可以在字符串上使用 split 来获取位置数据:

    soup.script.string.split()
    Output:
    ['var',
     'myvar',
     '=',
     '{',
     'productid:',
     '"101",',
     'productname:',
     '"Abc",',
     '};']
    

    PRODUCT_ID:

    soup.script.string.split()[5].split('"')[1]
    Output:
    '101'
    

    产品名称:

    soup.script.string.split()[7].split('"')[1]
    Output:
    'Abc'
    
  • 1

    简单来说,我将使用正则表达式

    import re
    
    .....
    data = soup.find_all('script', type='text/javascript')
    productid = re.search(r'productid:\s*"(.*?)"', data[0].text).group(1)
    print(productid)
    
  • 0

    有两种方法 . 容易,错误 . 或者不那么容易,但是正确的 .

    我不会向您推荐简单的方法 . 正确的方法是使用Javascript解析器 . 对于现代Javascript,esprima是一个不错的选择 . 有一个interactive online demo,它也可用作Python module .

    import esprima
    
    # script body as extracted from beautifulsoup
    script_text = """
      var myvar = {
        productid: "101",
        productname: "Abc",
      };
    """;
    
    tokens = esprima.tokenize(script_text)
    

    在这个简单的脚本中,没有太多的事情发生 . 原始令牌列表足以获得您想要的值 . 它看起来像这样:

    [
        {
            "type": "Keyword",
            "value": "var"
        },
        {
            "type": "Identifier",
            "value": "myvar"
        },
        {
            "type": "Punctuator",
            "value": "="
        },
        {
            "type": "Punctuator",
            "value": "{"
        },
        {
            "type": "Identifier",
            "value": "productid"
        },
        {
            "type": "Punctuator",
            "value": ":"
        },
        {
            "type": "String",
            "value": "\"101\""
        },
        {
            "type": "Punctuator",
            "value": ","
        },
        {
            "type": "Identifier",
            "value": "productname"
        },
        {
            "type": "Punctuator",
            "value": ":"
        },
        {
            "type": "String",
            "value": "\"Abc\""
        },
        {
            "type": "Punctuator",
            "value": ","
        },
        {
            "type": "Punctuator",
            "value": "}"
        },
        {
            "type": "Punctuator",
            "value": ";"
        }
    ]
    

    迭代列表并选择所需的值 .

    token_iterator = iter(tokens)
    
    for token in token_iterator:
        if token["type"] == "Identifier" and token["value"] == "productname":
            # the token after the next must be the one that holds the associated value
            value_token = next(next(token_iterator))
            productname = value_token["value"]
    

    对于更复杂的情况,可能需要将脚本解析为树并遍历树 .

    tree = esprima.parse(script_text)
    

    树更复杂(您可以在交互式页面上查看它),但作为交换,它包含普通令牌列表中缺少的所有上下文信息 . 然后,您将使用访问者模式将此树行走到特定位置 . 如果你有兴趣,Python包有一个example how to use the visitor pattern .

相关问题