我们右键
![171546508-a22e50275383ab15](http://jbcdn2.b0.upaiyun.com/2017/02/5f65ad0996afcd724d1c885f5625f8f8.png)
复制出来的结果 //*[@id="posts"]
,这个
我们现在来使用这个 XPath 获取所有的 HTML 数据.在
Post.m
添加如下方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
+
(
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
中调用这个方法:
1
2
3
4
5
6
7
8
|
@
implementation
ViewController
-
(
void
)
viewDidLoad
{
[
super
viewDidLoad
]
;
[
Post
getNewPosts
]
;
}
@
end
|
运行后查看 Console, 我们已经可以获取到每篇文章的 HTMl 了,然后我们再来解析每篇文章的具体数据.
切换到 FireBug,展开其中一篇文章的节点,
![181546508-01664bc64b015580](http://jbcdn2.b0.upaiyun.com/2017/02/2fa0432ff63db0c1d913e7c6ab37d610.png)
我们可以看到<h2 class="title">
节点下的
<a href="/post/jazzhands/jazzhands-yuan-ma-shi-xian-fen-xi">
<i class="fa fa-leaf"></i>
JazzHands 源码实现分析</a>
标签中,有文章的具体Url, 和文章标题,
<div class="info">
节点下的,
<span class="date">
<i class="fa fa-clock-o"></i>
2016-03-04 21:39</span>
标签有文章发布的时间,此时我们可以右键点击节点,复制文章标题,发布时间等节点的 XPath,
但这里我们使用相对的 XPath.
每篇文章的 HTML 结构如下:
文章标题 Url等内容
所以我们的
- 文章 Url XPath : “h2/a”
- 文章标题 XPath : a 标签的
href
属性值 - 文章发布时间 XPath : “div[2]/span[1]”
接下来我们来解析每一篇文章的详细数据
在 Post.m
中添加方法:
1
2
3
4
5
6
7
8
9
10
|
+
(
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
方法:如下
1
2
3
4
5
6
7
8
9
|
.
.
.
[
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
1
2
3
|
-
(
void
)
setPostUrl
:
(
NSString *
)
postUrl
{
_postUrl
=
[
kUrlStr
stringByAppendingString
:
postUrl
]
;
}
|
我们在下图位置打断点查看结果:
![191546508-17ea6701f15a54d1](http://jbcdn2.b0.upaiyun.com/2017/02/7463de7ff25a50d8c8ab9c3a10a0b972.png)
运行起来,结果如下:
![191546508-17ea6701f15a54d1](http://jbcdn2.b0.upaiyun.com/2017/02/7463de7ff25a50d8c8ab9c3a10a0b972.png)
至此我们已经能使用 FireBug + Ono + XPath 来解析 HTML 数据
我就使用这个办法获取我们学校教务管理系统 HTML,制作了一个统计成绩,计算绩点的 App.
补充
- FireBug 是一个很强大前端调试工具.
- 还可以使用
正则表达式
来解析 HTML 数据.不过从 StackOverflow 讨论 来看 ,并推荐使用正则来解析 HTML 数据. - RayWonderLich 有一篇比较老的教程 ,使用类似的技术解析 HTML
- 最最后,很重要的一点,HTML 数据可能经常会变动,尤其那个网页还不是我们自己能管理的网页,所以 XPath 随时可能解析失败,
如果你一定要使用 XPath 来解析 HTML 数据,可以在服务端进行这个操作,然后修改成 API 的形式,让手机端像以前一样 GET JSON 数据.
同时,服务端还可以设置异常处理,缓存等策略.
本文 Demo 可以在 GitHub 中获取
转自:http://ios.jobbole.com/92961/