【问题标题】:Can I use BeautifulSoup to dig into inline JavaScript?我可以使用 BeautifulSoup 来挖掘内联 JavaScript 吗?
【发布时间】:2015-01-25 13:55:47
【问题描述】:

我想从一系列页面中抓取数据块,这些页面将数据隐藏在脚本标记内的 JSON 对象中。我对 BeautifulSoup 相当满意,但我想我可能会在尝试使用它从 JavaScript 中获取数据时找错了树。

页面的结构大致是这样的:

...
<script>
  $(document).ready(function(){
    var data = $.data(graph_selector, [
         { data: charts.createData("Stuff I want")}
    ])};
</script>

head 和 body 各有无数个脚本,但每页只有一个 var data。我不确定如何为 BeautifulSoup 识别这个特定的&lt;script&gt;,除非var data 存在

我可以这样做吗?还是我需要其他工具?

【问题讨论】:

  • 我会使用 BeautifulSoup 找到原始 javascript 字符串,然后使用正则表达式来获取“我想要的东西”Somewhat relatedsomething like this
  • 但是等式中 BeautifulSoup 的值相当低。它允许您找到&lt;script&gt; 节点,但一开始这并不难。 (正确地,你应该忽略任何被注释掉的,但这在现实中并不是一个大问题。)

标签: javascript python beautifulsoup


【解决方案1】:

BeautifulSoup 是一个 HTML 解析器,它不能解析 javascript 代码。

以下是您的选择:

  1. 使用像slimit这样的javascript解析器

    from bs4 import BeautifulSoup
    from slimit import ast
    from slimit.parser import Parser
    from slimit.visitors import nodevisitor
    
    data = """
    <script>
        var data = $.data(graph_selector, [
             { data: charts.createData("Stuff I want")}
        ]);
    </script>
    """
    
    soup = BeautifulSoup(data)
    script = soup.find('script')
    
    
    parser = Parser()
    tree = parser.parse(script.text)
    print next(node.args[0].value for node in nodevisitor.visit(tree)
               if isinstance(node, ast.FunctionCall) and node.identifier.identifier.value == 'createData')
    # prints "Stuff I want"
    

    请注意,为了一个工作示例和解析错误,我不得不删减脚本。可能不适用于您的真实脚本内容,请检查。

  2. 使用正则表达式(最简单但不可靠的选项,所以不要在生产代码中使用它,除非您也可以控制 JS 代码并且可以做出所需的保证):

    import re
    from bs4 import BeautifulSoup
    
    data = """
    <script>
    $(document).ready(function() {
    var data = $.data(graph_selector, [{data: charts.createData("Stuff I want")}])};
    </script>
    """
    
    soup = BeautifulSoup(data)
    script = soup.find('script')
    
    pattern = r'charts.createData\("(.*?)"\)'
    print re.search(pattern, script.text).group(1)  # prints "Stuff I want"
    
  3. 让smth执行javascript代码:selenium(真实浏览器),或V8,或PyExecJS

【讨论】:

  • @ivan_pozdeev 感谢您的重要说明。这就是为什么我把这个选项放在第二个位置,还为第一个选项添加了一个工作示例。
猜你喜欢
  • 2015-06-11
  • 1970-01-01
  • 2016-03-03
  • 2015-04-29
  • 2012-11-14
  • 2015-02-13
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多