【问题标题】:Extract a variable value in JavaScript code from HTML从 HTML 中提取 JavaScript 代码中的变量值
【发布时间】: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

标签: javascript html ios swift regex


【解决方案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 我看到一些正则表达式代码...)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-02
  • 2017-09-03
  • 2011-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多