如何在UIWebView中获取HTML页面的标题?

146
我需要从在UIWebView中显示的HTML页面中提取标题标签的内容。最可靠的方法是什么?
我知道可以这样做:
- (void)webViewDidFinishLoad:(UIWebView *)webView{
    NSString *theTitle=[webView stringByEvaluatingJavaScriptFromString:@"document.title"];
}

然而,仅当启用javascript时才有效。或者,我可以仅扫描HTML代码的文本以获取标题,但这感觉有点麻烦,如果页面作者在其代码中进行了奇怪的操作,则可能会变得脆弱。如果到了那个地步,使用iPhone API处理html文本的最佳方法是什么?
我觉得我忘记了一些显而易见的东西。是否有比这两个选择更好的方法?
更新:根据此问题的答案:UIWebView:Can You Disable Javascript?似乎没有办法在UIWebView中关闭Javascript。因此,上面的Javascript方法将始终有效。

1
+1 我也不得不使用 @"document.title" 方法。 - Dave DeLong
我刚刚在寻找这个问题的解决方案,但是一想到要解析HTML就感到有些害怕。你提供的解决方案非常聪明。 - margusholland
请参考类似SO问题的以下答案:https://dev59.com/lHE95IYBdhLWcg3wdtqj#2313430 - fishinear
这个门户网站中有很多链接,比如:http://stackoverflow.com/questions/11704560/ios-uiwebview-title-doesnt-update-unless-calling-this-code-twice 或者 https://dev59.com/lHE95IYBdhLWcg3wdtqj#2313430。 - Kamil Wozniak
苹果支持社区也有相同的答案 - Daniel
7个回答

89

对于那些只是滑动屏幕寻找答案的人:

- (void)webViewDidFinishLoad:(UIWebView *)webView{
    NSString *theTitle=[webView stringByEvaluatingJavaScriptFromString:@"document.title"];
}

由于在UIWebView中无法关闭Javascript,因此这将始终起作用。


如果网页的编码不是'utf-8',使用此方法会导致标题混乱。 - Xiao
Swift 4怎么样? - Jayprakash Dubey

8
< p > WKWebView有一个'title'属性,只需要像这样操作即可:

func webView(_ wv: WKWebView, didFinish navigation: WKNavigation!) {
    title = wv.title
}

我认为目前不适合使用 UIWebView


3
如果启用了JavaScript,请使用以下内容:
NSString *theTitle=[webViewstringByEvaluatingJavaScriptFromString:@"document.title"];

如果禁用了 Javascript,请使用以下方法:
NSString * htmlCode = [NSString stringWithContentsOfURL:[NSURL URLWithString:@"http://www.appcoda.com"] encoding:NSASCIIStringEncoding error:nil];
NSString * start = @"<title>";
NSRange range1 = [htmlCode rangeOfString:start];

NSString * end = @"</title>";
NSRange range2 = [htmlCode rangeOfString:end];

NSString * subString = [htmlCode substringWithRange:NSMakeRange(range1.location + 7, range2.location - range1.location - 7)];
NSLog(@"substring is %@",subString);

我在 NSMakeRange 中使用 +7 和 -7 来消除 <title> 的长度,即 7。

现在你能在UIWebview中禁用Javascript吗?回到2010年,你是不能的。 - TechZen
我不了解 IOS 8 之前的版本,但你可以这样做:进入设置 --> Safari --> 高级 --> JavaScript 开/关。 - Pawandeep Singh
你如何在代码中判断JavaScript是否启用或禁用? - Eddie

2

编辑:刚刚看到你已经找到答案了...太棒了

我刚刚学会了这个!要做到这一点,甚至不需要在UIWebView中显示它。(但是因为你正在使用它,所以可以获取当前页面的URL)

无论如何,这里是代码和一些(薄弱的)解释:

    //create a URL which for the site you want to get the info from.. just replace google with whatever you want
    NSURL *currentURL = [NSURL URLWithString:@"http://www.google.com"];
    //for any exceptions/errors
    NSError *error;
    //converts the url html to a string
    NSString *htmlCode = [NSString stringWithContentsOfURL:currentURL encoding:NSASCIIStringEncoding error:&error];

现在我们有了HTML代码,那么如何获取标题呢?在每个基于HTML的文档中,标题都是由<title>和</title>标记指示的。因此,最简单的方法可能就是搜索htmlCode字符串中的<title>和</title>,并将其子串化以获取其中的内容。

    //so let's create two strings that are our starting and ending signs
    NSString *startPoint = @"<title>";
    NSString *endPoint = @"</title>";
    //now in substringing in obj-c they're mostly based off of ranges, so we need to make some ranges
    NSRange startRange = [htmlCode rangeOfString:startPoint];
    NSRange endRange = [htmlCode rangeOfString:endPoint];
    //so what this is doing is it is finding the location in the html code and turning it
    //into two ints: the location and the length of the string
    //once we have this, we can do the substringing!
    //so just for easiness, let's make another string to have the title in
    NSString *docTitle = [htmlString substringWithRange:NSMakeRange(startRange.location + startRange.length, endRange.location)];
    NSLog(@"%@", docTitle);
    //just to print it out and see it's right

这就是全部的内容了!总之,为了解释docTitle中所发生的混乱,如果我们只是通过说NSMakeRange(startRange.location, endRange.location)来创建一个范围,我们将获得startString(也就是)的标题和文本,因为位置是字符串的第一个字符。
因此,为了偏移这一点,我们只需添加字符串的长度即可。请注意,此代码未经测试。如果出现任何问题,可能是拼写错误,或者我在不应该添加指针时添加了指针。
如果标题有点奇怪而且不完全正确,请尝试调整NSMakeRange - 我的意思是添加/减去不同的字符串长度/位置 - 任何看起来合理的东西。
如果您有任何问题或者出现任何问题,请随时提问。这是我在这个网站上的第一个答案,所以如果有点杂乱无章,我很抱歉。

1

这是Swift 4版本,基于这里的答案。

func webViewDidFinishLoad(_ webView: UIWebView) {
    let theTitle = webView.stringByEvaluatingJavaScript(from: "document.title")
}

0

我目前没有使用webviews的经验,但我相信它会将标题设置为页面标题,所以我建议的一个技巧是在webview上使用一个类别,并覆盖self.title的setter,这样你就可以向你的对象添加一条消息或修改某些属性来获取标题。

你能试试看告诉我它是否有效吗?


0
如果您在代码中经常需要使用它,我建议您将一个函数添加到“extension UIWebView”中,就像这样。
extension UIWebView {

    func title() -> String {
        let title: String = self.stringByEvaluatingJavaScript(from: "document.title")!
        return title
    }
}

或者最好使用WKWebView。

不幸的是,它在ARKit中的支持不太好。我不得不放弃WKWebView。我无法将网站加载到webView中。如果有人对此问题有解决方案 -> 我有一个类似的问题,那将会非常有帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接