复制 XPath.png
复制出来的结果 //*[@id="posts"],这个
在 Post.m 添加如下方法:
+(NSArray*)getNewPosts{ NSMutableArray *array=[NSMutableArray array]; NSData *data= [NSData dataWithContentsOfURL:[NSURL URLWithString:kUrlStr]]; //下载网页数据 NSError *error; ONOXMLDocument *doc=[ONOXMLDocument HTMLDocumentWithData:data error:&error]; ONOXMLElement *postsParentElement= [doc firstChildWithXPath:@"//*[@id='posts']"]; //寻找该 XPath 代表的 HTML 节点, //遍历其子节点, [postsParentElement.children enumerateObjectsUsingBlock:^(ONOXMLElement *element, NSUInteger idx, BOOL * _Nonnull stop) { NSLog(@"%@",element); }]; return array;}
并在ViewController.m 中调用这个方法:
@implementation ViewController- (void)viewDidLoad { [super viewDidLoad]; [Post getNewPosts];}@end
运行后查看 Console, 我们已经可以获取到每篇文章的 HTMl 了,然后我们再来解析每篇文章的具体数据.
切换到 FireBug,展开其中一篇文章的节点,
文章 HTML 节点.png
我们可以看到
节点下的
标签中,有文章的具体Url, 和文章标题,
- 2016-03-04 21:39
标签有文章发布的时间,此时我们可以右键点击节点,复制文章标题,发布时间等节点的 XPath,但这里我们使用相对的 XPath.每篇文章的 HTML 结构如下:
-
- 文章标题 Url等内容
所以我们的
- 文章 Url XPath : "h2/a"
- 文章标题 XPath : a 标签的 href 属性值
- 文章发布时间 XPath : "div[2]/span[1]"
接下来我们来解析每一篇文章的详细数据
在 Post.m 中添加方法:
+(instancetype)postWithHtmlStr:(ONOXMLElement*)element{ Post *p=[Post new]; ONOXMLElement *titleElement= [element firstChildWithXPath:@"h2/a"]; // 根据 XPath 获取含有文章标题的 a 标签 p.postUrl= [titleElement valueForAttribute:@"href"]; //获取 a 标签的 href 属性 p.title= [titleElement stringValue]; ONOXMLElement *dateElement= [element firstChildWithXPath:@"div[2]/span[1]"]; //根据 XPath 获取文章发布时间 span 标签 p.postDate= [dateElement stringValue]; return p;}
然后修改 +(NSArray*)getNewPosts方法:如下
...[postsParentElement.children enumerateObjectsUsingBlock:^(ONOXMLElement *element, NSUInteger idx, BOOL * _Nonnull stop) { //NSLog(@"%@",element); Post *post=[Post postWithHtmlStr:element]; if(post){ [array addObject:post]; } }];...
最后因为我们我们获取到的 HTMl 的文章 Url 是相对 Url, 类似/post/jazzhands/jazzhands-yuan-ma-shi-xian-fen-xi所以我们在 Setter 方法中拼接域名 , http://BigPi.me
-(void)setPostUrl:(NSString *)postUrl{ _postUrl=[kUrlStr stringByAppendingString:postUrl];}
我们在下图位置打断点查看结果:
代码断点.png
运行起来,结果如下:
抓取文章数据结果.png
至此我们已经能使用 FireBug + Ono + XPath 来解析 HTML 数据
我就使用这个办法获取我们学校教务管理系统 HTML,制作了一个统计成绩,计算绩点的 App.
补充
- FireBug 是一个很强大前端调试工具.
还可以使用 正则表达式 来解析 HTML 数据.不过从 StackOverflow 讨论 来看 ,并推荐使用正则来解析 HTML 数据.
RayWonderLich 有一篇比较老的教程 ,使用类似的技术解析 HTML
最最后,很重要的一点,HTML 数据可能经常会变动,尤其那个网页还不是我们自己能管理的网页,所以 XPath 随时可能解析失败,如果你一定要使用 XPath 来解析 HTML 数据,可以在服务端进行这个操作,然后修改成 API 的形式,让手机端像以前一样 GET JSON 数据.同时,服务端还可以设置异常处理,缓存等策略.