在开发中,大部分会使用 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下删除空行的几种方法

    在查看linux下的配置文件时,为了便于一目了然的查看,经常会删除空行和#头的行.而linux在删除空行的方法很多,grep.sed.awk.tr等工具都能实现.现总结如下: 1.grep grep ...

  2. CSS-透明背景色兼容

    IE 不支持透明背景色 使用fileter div{ backgournd: #666; filter:alpha(opacity=50); -moz-opacity:0.5; opacity:0.5 ...

  3. Java+Selenium自动化测试学习(一)

    自动化测试基本流程 1.设置chromedriver的地址System.setProperty(); 2.创建一个默认浏览器ChromeDriver driver = new ChromeDriver ...

  4. 虚拟函数是否应该被声明仅为private/protected?

    问题导入 我想对于大家来说,虚拟函数并不能算是个陌生的概念吧.至于怎么样使用它,大部分人都会告诉我:通过在子类中重写(override)基类中的虚拟函数,就可以达到OO中的一个重要特性——多态(pol ...

  5. Git - git bash 在 windows 下创建软连接

    1. 概述 使用 git bash 在 windows 下创建软连接 或者叫 快捷方式 感谢 Tony 老师的帮助 Tony 的技术笔记 Windows 使用 ln -s 创建软链接 2. 问题 需求 ...

  6. Go递归函数

    package main import "fmt" func main() { /* 递归函数(recursion):一个函数自己调用自己,就叫做递归函数. 递归函数要有一个出口, ...

  7. ftrace使用

    前段时间遇到个问题,有个后继音频数据处理线程调度不及时导致音频输出延迟,音视频不同步. 因此从系统上入手,采用ftrace进行debug,来看有哪些线程会去抢占音频数据处理线程. ftrace 提供了 ...

  8. C\C++改变鼠标样式

    改变鼠标样式可以使用SetClassLong函数 HCURSOR hcur = LoadCursor(NULL, IDC_CROSS); //加载系统自带鼠标样式 HWND hwnd = GetHWn ...

  9. java 数据类型优先级

    由低到高:byte,short,char—> int —> long—> float —> double 1. 不能对boolean类型进行类型转换. 2. 不能把对象类型转换 ...

  10. MyBatis-Spring整合之方式1

    导入相关包:Spring包:Spring架包 MyBatis包:MyBatis架包 整合包:Mybatis-Spring整合包 编写实体类User,实体类的sql映射文件,映射内容如下: <?x ...