在开发中,大部分会使用 JSON 进行数据解析,偶尔会用到 HTML。

  使用 Objective-C 解析 HTML 或者 XML,系统自带有两种方式一个是通过 libxml,一个是通过 NSXMLParser。

  libxml性能较好,且可以结合urlconnection实现边下载边解析,在要求快速 、分批响应UI到情况下较为有用,NSXMLParser基本没什么优势,不如使用第三方工具。

  Hpple,它是一个轻量级的包装框架,可以很好的解决这个问题,尤其是它支持HTML的解析,是其他XML类库所不及的地方,它是用XPath来定位和解析HTML或者XML。

  使用方法:

  1> 在 GitHub 上下载 Hpple

  2> 把 Hpple 文件夹拖进项目工程;

  3> 添加依赖库 libxml2.2.dylib、

  4> 配置 libxml2.2 索引路径(否则编译报错)如图

  

  解析本地 HTML 文件:

NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"]];
TFHpple *doc = [[TFHpple alloc] initWithHTMLData:data];
NSArray *elements = [doc searchWithXPathQuery:@"//a[@class='sponsor']"];
TFHppleElement *element = [elements objectAtIndex:];
[element text]; // The text inside the HTML element (the content of the first text node)
[element tagName]; // "a"
[element attributes]; // NSDictionary of href, class, id, etc.
[element objectForKey:@"href"]; // Easy access to single attribute
[element firstChildWithTagName:@"b"]; // The first "b" child node
NSLog(@"%@\ntxt = %@\n tagName = %@\n attributes = %@", elements,[element text],[element tagName],[element attributes]);

  解析网络HTML:

NSData *htmlData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:@"http://world.chinadaily.com.cn/2017-08/02/content_30329852.htm"]];
TFHpple *xpathParser = [[TFHpple alloc] initWithHTMLData:htmlData];
NSArray *divArray = [xpathParser searchWithXPathQuery:@"//div[@class=\"article\"]"];
NSMutableString *str = [[NSMutableString alloc] init];
TFHppleElement *element = [divArray objectAtIndex:];
[str appendString:[element content]];
NSLog(@"%@", str);

  HTML 解析测试:

- (void)setUp
{
NSBundle *testBundle = [NSBundle bundleForClass:[self class]];
NSURL *testFileUrl = [testBundle URLForResource:TEST_DOCUMENT_NAME withExtension:TEST_DOCUMENT_EXTENSION];
NSData * data = [NSData dataWithContentsOfURL:testFileUrl];
self.doc = [[TFHpple alloc] initWithHTMLData:data];
} - (void)testInitializesWithHTMLData
{
XCTAssertNotNil(self.doc.data);
XCTAssertTrue([self.doc isMemberOfClass:[TFHpple class]]);
} // doc.search("//p[@class='posted']")
- (void)testSearchesWithXPath
{
NSArray *a = [self.doc searchWithXPathQuery:@"//a[@class='sponsor']"];
XCTAssertEqual([a count], ); TFHppleElement * e = [a objectAtIndex:];
XCTAssertTrue([e isMemberOfClass:[TFHppleElement class]]);
} - (void)testFindsFirstElementAtXPath
{
TFHppleElement *e = [self.doc peekAtSearchWithXPathQuery:@"//a[@class='sponsor']"]; XCTAssertEqualObjects([e content], @"RailsMachine");
XCTAssertEqualObjects([e tagName], @"a");
} - (void)testSearchesByNestedXPath
{
NSArray *a = [self.doc searchWithXPathQuery:@"//div[@class='column']//strong"];
XCTAssertEqual([a count], ); TFHppleElement * e = [a objectAtIndex:];
XCTAssertEqualObjects([e content], @"PeepCode");
} - (void)testPopulatesAttributes
{
TFHppleElement *e = [self.doc peekAtSearchWithXPathQuery:@"//a[@class='sponsor']"]; XCTAssertTrue([[e attributes] isKindOfClass:[NSDictionary class]]);
XCTAssertEqualObjects([[e attributes] objectForKey:@"href"], @"http://railsmachine.com/");
} - (void)testProvidesEasyAccessToAttributes
{
TFHppleElement *e = [self.doc peekAtSearchWithXPathQuery:@"//a[@class='sponsor']"]; XCTAssertEqualObjects([e objectForKey:@"href"], @"http://railsmachine.com/");
}

  XML 解析测试:

- (void)setUp
{
[super setUp]; NSBundle *testBundle = [NSBundle bundleForClass:[self class]];
NSURL *testFileUrl = [testBundle URLForResource:TEST_DOCUMENT_NAME withExtension:TEST_DOCUMENT_EXTENSION];
NSData * data = [NSData dataWithContentsOfURL:testFileUrl];
self.doc = [[TFHpple alloc] initWithXMLData:data];
} - (void)testInitializesWithXMLData
{
XCTAssertNotNil(self.doc.data);
XCTAssertTrue([self.doc isMemberOfClass:[TFHpple class]]);
} // item/title,description,link
- (void)testSearchesWithXPath
{
NSArray *items = [self.doc searchWithXPathQuery:@"//item"];
XCTAssertEqual([items count], 0x0f); TFHppleElement * e = [items objectAtIndex:];
XCTAssertTrue([e isMemberOfClass:[TFHppleElement class]]);
} - (void)testFindsFirstElementAtXPath
{
TFHppleElement *e = [self.doc peekAtSearchWithXPathQuery:@"//item/title"]; XCTAssertEqualObjects([e content], @"Objective-C for Rubyists");
XCTAssertEqualObjects([e tagName], @"title");
} - (void)testSearchesByNestedXPath
{
NSArray *elements = [self.doc searchWithXPathQuery:@"//item/title"];
XCTAssertEqual([elements count], 0x0f); TFHppleElement * e = [elements objectAtIndex:];
XCTAssertEqualObjects([e content], @"Objective-C for Rubyists");
} - (void)testAtSafelyReturnsNilIfEmpty
{
TFHppleElement * e = [self.doc peekAtSearchWithXPathQuery:@"//a[@class='sponsor']"];
XCTAssertEqualObjects(e, nil);
} // Other Hpricot methods:
// doc.at("body")['onload']
// (doc/"#elementID").inner_html
// (doc/"#elementID").to_html
// doc.at("div > div:nth(1)").css_path
// doc.at("div > div:nth(1)").xpath

  字符串解析测试:

- (void)setUp {
[super setUp]; NSString *htmlString = @"String with a link <a href=\"http://www.google.com\">This is a link</a> and the end";
NSData *data = [htmlString dataUsingEncoding:NSUTF8StringEncoding];
self.doc = [[TFHpple alloc] initWithHTMLData:data];
} - (void)testTextNodeCount
{
NSArray *textNodes = [self.doc searchWithXPathQuery:@"//text()"];
XCTAssertEqual(textNodes.count, );
} - (void)testFirstTextNodeContent
{
TFHppleElement *e = [self.doc peekAtSearchWithXPathQuery:@"//text()"];
XCTAssertEqualObjects([e content], @"String with a link ");
} - (void)testALinkContent
{
TFHppleElement *e = [self.doc peekAtSearchWithXPathQuery:@"//a"];
XCTAssertEqualObjects([e content], @"This is a link"); } - (void)testHref
{
TFHppleElement *e = [self.doc peekAtSearchWithXPathQuery:@"//a"];
XCTAssertEqualObjects([e objectForKey:@"href"], @"http://www.google.com");
}

  

Hpple -- 一个 HTML 解析工具的更多相关文章

  1. NSXMLParser自定义的一个xml解析工具

    // // DenglXMLParser.h // #import <Foundation/Foundation.h> @interface DenglXMLParser : NSXMLP ...

  2. java 写一个JSON解析的工具类

    上面是一个标准的json的响应内容截图,第一个红圈”per_page”是一个json对象,我们可以根据”per_page”来找到对应值是3,而第二个红圈“data”是一个JSON数组,而不是对象,不能 ...

  3. Dubbo 泛化调用的参数解析问题及一个强大的参数解析工具 PojoUtils

    排查了3个多小时,因为一个简单的错误,发现一个强大的参数解析工具,记录一下. 背景 Nodejs 通过 tether 调用 Java Dubbo 服务.请求类的某个参数对象 EsCondition 有 ...

  4. [开源]C#二维码生成解析工具,可添加自定义Logo

    二维码又称 QR Code,QR 全称 Quick Response,是一个近几年来移动设备上超流行的一种编码方式,它比传统的 Bar Code 条形码能存更多的信息,也能表示更多的数据类型:比如:字 ...

  5. CocosStudio文件解析工具CsdAnalysis

    起因 因为工作需要,所以需要使用CocosStudio来制作界面动画什么的.做完了发现需要找里边对象的时候会有很长一串代码,感觉不是很爽.之前写OC代码的时候可以吧程序中的对象指针跟编辑器中的对象相对 ...

  6. Json解析工具Jackson(使用注解)

    原文http://blog.csdn.net/nomousewch/article/details/8955796 接上一篇文章Json解析工具Jackson(简单应用),jackson在实际应用中给 ...

  7. Json解析工具Jackson(简单应用)

    原文http://blog.csdn.net/nomousewch/article/details/8955796 概述 Jackson库(http://jackson.codehaus.org),是 ...

  8. Java XML解析工具 dom4j介绍及使用实例

    Java XML解析工具 dom4j介绍及使用实例 dom4j介绍 dom4j的项目地址:http://sourceforge.net/projects/dom4j/?source=directory ...

  9. (转)AVI文件格式解析+AVI文件解析工具

    AVI文件解析工具下载地址:http://download.csdn.net/detail/zjq634359531/7556659 AVI(Audio Video Interleaved的缩写)是一 ...

随机推荐

  1. linux centos7分区

    哈喽! 我今天来分享一下Linux的分区,本次我使用的是LinuxCentos7版本为例,使用虚拟机,命令是fdisk Linux分区有4个主分区及扩展分区,逻辑分区. 首先给虚拟机添加8G硬盘(硬盘 ...

  2. 浅谈对Jquery+JSON+WebService的使用小结

    https://www.jb51.net/article/36207.htm  更新时间:2013年04月28日 12:19:55   作者:    我要评论   本篇文章介绍了对Jquery+JSO ...

  3. SpringMVC--使用hibernate validator数据校验

    JSR 303 Spring3开始支持JSR 303 验证框架,JSR303是Java为Bean数据合法性校验所提供的标准框架.JSR 303 支持XML和注解风格的验证,通过在Bean属性上标注类似 ...

  4. ACM-ICPC实验室20.2.21测试-图论(二)

    A.患者的编号 给出一个有向图,要求你输出字典序最小的拓扑排序. 常规拓扑排序是做不了的,正解是反向建图,同时用大根堆的优先队列维护,保证每次优先访问编号大的结点,再反向输出~ #include< ...

  5. c++调用自己编写的静态库(通过eclipse)

    转:https://blog.csdn.net/hao5335156/article/details/80282829 参考:https://blog.csdn.net/u012707739/arti ...

  6. Codeforces 1315B Homecoming (二分)

    After a long party Petya decided to return home, but he turned out to be at the opposite end of the ...

  7. AD 快捷键设置

    TAA 设置自动标记原件位号 AR 设置元件向右对齐 AL 设置元件向左对齐 MS 移动所选择 CO 错误报告设置 CTRL + w 设置电气线 PN 添加net label TG 打开封装管理器 P ...

  8. 使用pyaudio播放无损音乐(wav)

    安装pyaudio sudo apt-get install python-pyaudio python3-pyaudio pip3 install pyaudio 执行第二步可能会遇到如下错误: 根 ...

  9. Codeforces Round #618 (Div. 1)A(观察规律)

    实际上函数值为x&(-y) 答案仅和第一个数字放谁有关 #define HAVE_STRUCT_TIMESPEC #include <bits/stdc++.h> using na ...

  10. JAVA基础学习(3)之循环

    3循环 3.1循环 3.1.1循环 一直要做的行为进行循环 3.1.2数数字 while(){}判断是否进行 数数字:number/10 //数数字Scanner in = new Scanner(S ...