Javascript 加载后获取HTML内容
我有一个Javascript 加载后获取HTML内容,javascript,html,ios,swift,Javascript,Html,Ios,Swift,我有一个共享扩展名,其中我得到了HTML,如下所示: @objc func actionButtonTapped(){ var html: String? if let item = extensionContext?.inputItems.first as? NSExtensionItem, let itemProvider = item.attachments?.first, itemProvider.has
共享扩展名
,其中我得到了HTML
,如下所示:
@objc func actionButtonTapped(){
var html: String?
if let item = extensionContext?.inputItems.first as? NSExtensionItem,
let itemProvider = item.attachments?.first,
itemProvider.hasItemConformingToTypeIdentifier("public.url") {
itemProvider.loadItem(forTypeIdentifier: "public.url", options: nil) { (url, error) in
if (url as? URL) != nil {
html = (self.getHTMLfromURL(url: url as? URL))
self.doStuff(html: html)
}
}
}
}
问题:
我得到的是HTML,但不是完整的内容。如何获取网站的完整HTML
-内容
更新:
原因是我想刮取任何产品的价格
,但有些网站没有在第一个HTML get
上加载price
这是一个很好的例子。如果您单击价格并检查它,您可以看到它在
类当前价格中。但是,如果我使用上述方法检索HTML
,则不会显示该类。根据我的了解,在加载客户端Javascript时存在一个问题,如果您使用Promise
,这将很有帮助
注意-看看这是否有用下面是一个使用URLSession和URLRequest的示例:
func retrieveHTML(from url: URL, completion: @escaping (String) -> Void) {
let request = URLRequest(url: url)
let session = URLSession(configuration: .ephemeral)
let task = session.dataTask(with: request) { (data, response, error) in
guard let data = data, error == nil else {
print("Data not found, error encountered: \(error!)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 {
let code = httpStatus.statusCode
if code >= 400 {
// You can do more here with these codes, but for sake of this example, we'll return
print("Received error code from HTTP Response. Code: \(code)")
return
}
if code == 301 || code == 302 {
// You should update the incoming URL as it is moving, but early return not needed
print("You could log this error here if desired")
}
}
if let responseString = String(data: data, encoding: .utf8) {
print("Data found, encoded as string")
completion(responseString)
}
}
task.resume()
}
在页面未完全加载的情况下,仍然可能会遇到错误,这取决于页面中JavaScript的呈现方式。这至少可以让您找到正确的方向。此函数将从后台线程的url字符串中查找HTML(以免锁定您的UI),然后在处理后,您可以在主线程上更新UI:
func getHtml(_ urlString: String, completion: @escaping (String?, Error?) -> Void) {
DispatchQueue.global(qos: .userInitiated).async(execute: {
guard let url = URL(string: urlString) else {
print("URLError: \(urlString) doesn't seem to be a valid URL")
return completion(nil, URLError.init(URLError.Code.badURL))
}
do {
let html = try String(contentsOf: url, encoding: .ascii)
print("HTML: \(html)")
return completion(html, nil)
} catch let error {
print("Error: \(error)")
return completion(nil, error)
}
})
}
用法:
getHtml("https://www.google.com", completion: { html, error in
if let e = error {
print(e)
// handle your error
return
}
print(html as Any)
DispatchQueue.main.async {
//update your UI on the main thread
}
})
更新:
您真的应该在服务器端抓取web内容。iOS不允许您在不显示WKWebView的情况下执行此操作
在iOS中,如果需要Chrome的“检查”功能之类的数据,则需要在WKWebView的didFinish函数中加载javascript:
谢谢你的回答。我以前从未使用过Javascript。有没有办法在Swift中实现这一点?您是否考虑过使用URLRequest和URLSession?session.dataTask返回的数据元素应可转换为字符串表示形式,然后您可以对其进行分析。@binaryPilot84抱歉,我没有完全理解您的意思。从未将urlrequest与urlsession一起使用。你能详细说明一下吗?:)你可以使用异步等待函数调用你不能在没有加载WKWebView的情况下在iOS中抓取web。我试过并打印了数据我认为它工作不正常?如果您尝试使用此链接,例如:价格在class=current price
中,但如果我直接查找current price
或甚至是199,95
,我在从您的函数中检索的数据中找不到它?我在这里遗漏了什么吗?事实上,我认为我从你的代码中得到的数据正是我从问题中的函数中得到的数据……从中检索到的HTML可能不是你想要的。这就是说,其中的javascript确实包含您需要的内容。该流具有用于后续查询的API URL,它返回一个相对简单的JSON流。它提供的链接是:/api/product/catalog/v3/stockprice?productIds=12373010&store=DE¤cy=EUR&keystredataversion=j42uv2x-26,您可以将该链接附加到基本url,使asos.com/api/product/catalog/v3/stockprice?productIds=12373010&store=DE¤cy=EUR&keystredataversion=j42uv2x-26。我将遍历生成的JSON以获取数据。那么我该如何从示例网站上获得价格呢?这并不能真正解决我的问题。我更新了我的问题,也许现在它更清楚了。@Chris,我更新了我的答案,但在iOS中,如果不显示WKWebView,你就无法真正做到这一点。你应该在服务器端抓取数据,然后将数据返回到你的应用程序。问题是,我在s共享扩展中使用了此功能,因此我可以从Safari访问我的应用程序,并从该扩展向我的应用程序添加内容。我不想在我的ShareExtension
中有一个WKWebView
,因为那没有什么意义。你明白我的意思了吗?嘿@Chris,我完全明白你想做什么,但不幸的是你需要在服务器端完成。目前,您无法在iOS中执行此操作。可能是因为苹果认为这可能会导致加载页面和解析页面的用户体验变慢。我知道的解决方法是在WKWebView中加载页面并加载Javascript。也许有一种方法可以在不显示的情况下加载WKWebView。
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
let doc = webView.evaluateJavaScript("document.documentElement.outerHTML", completionHandler: { html, error in
print(html)
})
}