从 HTML 中提取 JavaScript 代码中的变量值

Posted

技术标签:

【中文标题】从 HTML 中提取 JavaScript 代码中的变量值【英文标题】:Extract a variable value in JavaScript code from HTML 【发布时间】:2019-01-17 07:24:00 【问题描述】:

我正在使用名为 Kanna 的解析库获取网页的 html 代码。基本上精简版是这样的。

<!DOCTYPE html>
<html lang="en" class="no-js not-logged-in client-root">

<head>
    <meta charset="utf-8">
</head>

<body>

    <script type="text/javascript">
        window._sharedData =  
            // Some JSON
        ;
    </script>

    <script type="text/javascript">
        // Javascript code
    </script>

    <script type="text/javascript">
        // More Javascript code
    </script>

</body>

</html>

body 中有多个script 标签。我想使用名为window._sharedData 的变量访问那个变量并提取它的值,它是一个 JSON 字典。

我尝试使用正则表达式,但它返回 nil。也许我的模式有问题?

if let doc = try? HTML(url: mixURL, encoding: .utf8), let body = doc.body, let htmlText = body.text   

    let range = NSRange(location: 0, length: htmlText.utf8.count)
    let regex = try! NSRegularExpression(pattern: "/<script type=\"text/javascript\">window._sharedData = (.*)</script>/")
    let s = regex.firstMatch(in: htmlText, options: [], range: range)
    print(s)


或者有更好的方法吗?

【问题讨论】:

删除正则表达式模式中的第一个和最后一个/。在模式开始处添加(?s)。将.* 替换为.*?。在window 之前添加\\s*。并转义文字 . 请参阅 this demo。 @WiktorStribiżew 非常感谢!我试过你的模式。但是我不得不做出一些改变,因为在 Swift 中我不得不转义 ` like this \`。所以完整的模式看起来像这样(?s)&lt;script type=\"text/javascript\"&gt;\\s*window\\._sharedData = (.*?)&lt;/script&gt;。但不知何故它不匹配:/ 是的,要定义\,您必须在字符串文字中使用\\。这不是对正则表达式的更改,而是您在 Swift 代码中编写该字符串的方式。怎么没有?这就是它的样子:pattern: "(?s)&lt;script type=\"text/javascript\"&gt;\\s*window\\._sharedData = (.*?)&lt;/script&gt;"。如果它不起作用,则问题出在您的代码上。请注意,Swift 正则表达式适用于 UTF16 编码的字符串。尝试用htmlText.utf16.count替换htmlText.utf8.count 好吧,我已经尝试了我最初的建议,它返回Optional(&lt;_NSRegularExpressionNSTextCheckingResultResult: 0x00005582ba121120&gt;) @WiktorStribiżew 是的。当我像上面的代码一样将 html 作为字符串尝试时,它确实有效。但是由于某种原因,当我使用我使用该库动态获得的 html 代码时,它不会。让我分享一下我的demo project。 【参考方案1】:

这里是:

import Foundation
import Kanna

let htmlString = "<!DOCTYPE html><html lang=\"en\" class=\"no-js not-logged-in client-root\"><head> <meta charset=\"utf-8\"></head><body> <script type=\"text/javascript\"> window._sharedData =  \"string\": \"Hello World\" ; </script> <script type=\"text/javascript\"> </script> <script type=\"text/javascript\"> </script></body></html>"

guard let doc = try? HTML(html: htmlString, encoding: .utf8) else  print("Build DOM error"); exit(0) 

let body = doc.xpath("//script")
            .compactMap  $0.text 
            .filter  $0.contains("window._sharedData") 
            .map  $0.replacingOccurrences(of: " window._sharedData = ", with: "") 
            .map  $0.dropLast(2) 
            .first

print("body: ", body) 
// body:  Optional(" \"string\": \"Hello World\" ")

之后你可以检查那个身体不是零并且准备好了

【讨论】:

感谢您的回复。有没有办法获取window._sharedData 变量的值?只有 JSON 部分?这就是我实际卡住的地方。 @Isuru 已更新。 我正在尝试使用完整的 HTML 页面(不是问题中显示的精简版本),它仍然返回带有变量的完整块。见我的demo project。 你能提供网页的网址吗? 您还尝试在哪个文件中获得结果? (在 ViewController 我看到一些正则表达式代码...)

以上是关于从 HTML 中提取 JavaScript 代码中的变量值的主要内容,如果未能解决你的问题,请参考以下文章

没有用python代码提取的Javascript代码

有没有办法从 javascript 文档中提取列表?

仅使用 Javascript 从 HTML 字符串中提取元标记

JavaScript 使用innerHTML从HTML文件中提取信息

使用 html 或 javascript 从精灵表中提取单个帧

如何使用从 javascript/html 中的外部 php 文件中提取的 JSON 数据?