
我想解析下面这段 HTML 代码,这段代码属于 ?tab=tech 页面的代码。
<div class="cell item" style=""><div style="position: absolute; margin: -10px -10px 0px 650px;"></div> <table cellpadding="0" cellspacing="0" border="0" width="100%"> <tr> <td width="48" valign="top" align="center"><a href="/member/xiaobaike"><img src="//cdn.v2ex.co/gravatar/1d27a1b82bcc599bfd0ffad63f3a588b?s=48&d=retro" class="avatar" border="0" align="default" style="max-width: 48px; max-height: 48px;" /></a></td> <td width="10"></td> <td width="auto" valign="middle"><span class="item_title"><a href="/t/237254#reply3">新版 google+自扇狗脸</a></span> <div class="sep5"></div> <span class="small fade"><div class="votes"></div><a class="node" href="/go/android">Android</a> <strong><a href="/member/xiaobaike">xiaobaike</a></strong> 23 分钟前 最后回复来自 <strong><a href="/member/864766428">864766428</a></strong></span> </td> <td width="70" align="right" valign="middle"> <a href="/t/237254#reply3" class="count_livid">3</a> </td> </tr> </table> </div> 我用下面的代码获取了上面 html 代码的内容.
NSArray * elements = [doc searchWithXPathQuery:@"//div[@class='cell item']"]; TFHppleElement * element = [elements objectAtIndex:0]; 接下来应该怎么获取<a href="/member/xiaobaike"><img src="//cdn.v2ex.co/gravatar/1d27a1b82bcc599bfd0ffad63f3a588b?s=48&d=retro" class="avatar" border="0" align="default" style="max-width: 48px; max-height: 48px;" /></a>和<a href="/t/237254#reply3">新版 google+自扇狗脸</a> 里面的图片和文字。
1 black 2015-11-19 15:13:54 +08:00 [element firstChildWithClassName:@"avatar"]; [[element firstChildWithClassName:@"item_title"] firstChildWithTagName:@"a"]; |
OP @black 打印出来是空的( null )。。这是我实现的代码 ``` NSURL *URL = [NSURL URLWithString:@"?tab=tech"]; NSURLRequest *request = [NSURLRequest requestWithURL:URL]; AFHTTPRequestOperation *op = [[AFHTTPRequestOperation alloc] initWithRequest:request]; [op setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { NSData * data = responseObject; TFHpple * doc = [[TFHpple alloc] initWithHTMLData:data]; NSArray * elements = [doc searchWithXPathQuery:@"//div[@class='cell item']"]; TFHppleElement * element = [elements objectAtIndex:0]; NSLog(@"%@", [element firstChildWithClassName:@"avatar"]); NSLog(@"%@", [[element firstChildWithClassName:@"item_title"] firstChildWithTagName:@"a"]); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }]; [op start]; ``` |
3 black 2015-11-19 16:37:13 +08:00 不好意思,上面的代码是错误的。 方案一: 首先给 TFHppleElement 增加两个方法: - (TFHppleElement *)findFirstSubnodeWithClassName:(NSString *)className { for (TFHppleElement *child in self.children) { if ([[child objectForKey:@"class"] isEqualToString:className]) { return child; } TFHppleElement *find = [child findFirstSubnodeWithClassName:className]; if (find) { return find; } } return nil; } - (TFHppleElement *)findFirstSubnodeWithTagName:(NSString *)tagName { for (TFHppleElement *child in self.children) { if ([[child tagName] isEqualToString:tagName]) { return child; } TFHppleElement *find = [child findFirstSubnodeWithTagName:tagName]; if (find) { return find; } } return nil; } 然后代码改一下: [element findFirstSubnodeWithClassName:@"avatar"]; [[element findFirstSubnodeWithClassName:@"item_title"] findFirstSubnodeWithTagName:@"a"]; 方案二: 根据得到的 TFHppleElement 实例再创建一个 TFHpple 对象: NSData *elementData = [[element raw] dataUsingEncoding:NSUTF8StringEncoding]; TFHpple *elementHpple = [[TFHpple alloc] initWithHTMLData:elementData]; 然后再次使用 XPath 查询 avatar: TFHppleElement *avatarElement = [[elementHpple searchWithXPathQuery:@"//img[@class=\"avatar\""] firstObject]; |
4 xuyinan503 2015-11-19 16:56:09 +08:00 用 V2EX api 呗 p/7v9TEc53 |
5 UtopiaCHN OP @black 太感谢了,这个问题我折腾了好久,终于解决了。不过方案二报错了,错误信息是: XPath error : Invalid predicate XPath error : Invalid expression 2015-11-19 22:27:05.463 V2EX[14762:580730] Unable to evaluate XPath. 2015-11-19 22:27:05.464 V2EX[14762:580730] (null) |
6 UtopiaCHN OP @xuyinan503 里面没有分类页面的 api ,只能解析 html 。。。 |
7 black 2015-11-20 10:14:38 +08:00 XPath 写错了,改一下就好: TFHppleElement *avatarElement = [[elementHpple searchWithXPathQuery:@"//img[@class=\"avatar\"]"] firstObject]; |
9 UtopiaCHN OP @black 能不能再请教一个问题,我想拿到下面代码中的“ 2 小时 0 分钟前”,我用<span>节点的 content ( element.content )输出得到的是: Python meloncrashed 2 小时 0 分钟前。如果我想拿到“ 2 小时 0 分钟前”是不是只能从字符串层面进行处理呢? <span class="small fade"> <div class="votes"></div> <a class="node" href="/go/python">Python</a> <strong><a href="/member/meloncrashed">meloncrashed</a></strong> 2 小时 0 分钟前 </span> |
10 black 2015-11-22 07:58:32 +08:00 via iPhone 试试 element.text |
12 black 2015-11-23 18:42:06 +08:00 文本在 hpple 里抽象成 textNode, 遍历当前元素,找到所有的 textNode, 再去 textNode 集合里拿你想要的: 2 小时 0 分钟前 |
13 black 2015-11-23 18:43:42 +08:00 fr (TFHppleElement *child in self.children) { if ([child isTextNode]) { // ... } |
14 UtopiaCHN OP @black 输出来是空的。。 这是我的代码: NSArray *elements = [element searchWithXPathQuery:@"//span[@class='small fade']"]; e = [elements objectAtIndex:0]; for (TFHppleElement *child in e.children) { if ([child isTextNode]) { NSLog(@"%@", child.text); } } 处理的 html : <span class="small fade"> <div class="votes"></div> <a class="node" href="/go/python">Python</a> <strong><a href="/member/meloncrashed">meloncrashed</a></strong> 2 小时 0 分钟前 </span> |
15 black 2015-11-23 23:11:04 +08:00 via iPhone 建议楼主先研究一下源代码,分清楚 text 和 content 这两个方法分别返回什么。 打印语句改成 child.content 再试试吧。 |
16 UtopiaCHN OP @black 如果是: for (TFHppleElement *child in e.children) { if ([child isTextNode]) { NSLog(@"%@", child.content); } } 输出是: 2015-11-23 23:10:43.093 V2EX[34536:1463891] 2015-11-23 23:10:43.093 V2EX[34536:1463891] 几秒前 最后回复来自 处理的 html : <span class="small fade"><div class="votes"></div><a class="node" href="/go/java">Java</a> <strong><a href="/member/kanezeng">kanezeng</a></strong> 几秒前 最后回复来自 <strong><a href="/member/salmon5">salmon5</a></strong></span> |
19 black 2015-11-23 23:18:15 +08:00 via iPhone 期待楼主的 V2EX 客户端早日上架:) |