从 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)<script type=\"text/javascript\">\\s*window\\._sharedData = (.*?)</script>
。但不知何故它不匹配:/
是的,要定义\
,您必须在字符串文字中使用\\
。这不是对正则表达式的更改,而是您在 Swift 代码中编写该字符串的方式。怎么没有?这就是它的样子:pattern: "(?s)<script type=\"text/javascript\">\\s*window\\._sharedData = (.*?)</script>"
。如果它不起作用,则问题出在您的代码上。请注意,Swift 正则表达式适用于 UTF16 编码的字符串。尝试用htmlText.utf16.count
替换htmlText.utf8.count
好吧,我已经尝试了我最初的建议,它返回Optional(<_NSRegularExpressionNSTextCheckingResultResult: 0x00005582ba121120>)
。
@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 代码中的变量值的主要内容,如果未能解决你的问题,请参考以下文章
仅使用 Javascript 从 HTML 字符串中提取元标记
JavaScript 使用innerHTML从HTML文件中提取信息