我想解析下面这段 HTML 代码,这段代码属于 https://www.v2ex.com/?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"]; |
2
UtopiaCHN OP @black 打印出来是空的( null )。。这是我实现的代码
``` NSURL *URL = [NSURL URLWithString:@"https://www.v2ex.com/?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 1
不好意思,上面的代码是错误的。
方案一: 首先给 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 呗
https://www.v2ex.com/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 1
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 1
文本在 hpple 里抽象成 textNode, 遍历当前元素,找到所有的 textNode, 再去 textNode 集合里拿你想要的: • 2 小时 0 分钟前
|
13
black 2015-11-23 18:43:42 +08:00 1
for (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 客户端早日上架:)
|