這是什么?
通常服務(wù)器給客戶端返回的數(shù)據(jù)是JSON或是XML停忿,對(duì)于JSON數(shù)據(jù)解析,或許我們已經(jīng)輕車熟路了蚊伞,XML可能要麻煩一點(diǎn)席赂,但畢竟XML格式的數(shù)據(jù)已經(jīng)存在很久了,業(yè)內(nèi)也有很多解決方案的时迫。但之前自己寫的一個(gè)項(xiàng)目颅停,數(shù)據(jù)需要自己去網(wǎng)頁抓包來獲取,也就是如何通過HTML來解析數(shù)據(jù)掠拳。
神奇的第三方庫
之前對(duì)于這種方式完全沒有聽過癞揉,這是什么啊溺欧?喊熟?不過經(jīng)過多方查找,發(fā)現(xiàn)還有xpath這種語法(前端的大神不要打我哦)姐刁,身為一個(gè)iOS的開發(fā)人員芥牌,感覺發(fā)現(xiàn)了新大陸,然后在GitHub上找到mattt大神(著名的AFNetworking作者)寫的一個(gè)庫Ono聂使,簡(jiǎn)直太棒了8烊!
如何使用岩遗?
新建一個(gè)工程扇商,并將Ono使用pod導(dǎo)入進(jìn)來,注意,需要在 Info.plist 中添加兩行 App Transport Security Settings,和 Allow Arbitrary Loads YES, 來允許 HTTP 傳輸.
Demo中的網(wǎng)址是在搜狐體育抓到的一個(gè)HTML文件 http://cbadata.sports.sohu.com/iframes/top_sch_2015.html
在解析之前需要先知道什么是xpath--傳送門
ok,進(jìn)入正文
首先需要將HTML數(shù)據(jù)轉(zhuǎn)成NSData類型宿礁,然后生成ONOXMLDocument對(duì)象
NSMutableArray *array = [NSMutableArray array];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:kUrlStr]]; // 下載網(wǎng)頁數(shù)據(jù)
NSError *error = nil;
ONOXMLDocument *doc = [ONOXMLDocument HTMLDocumentWithData:data error:&error];
解析數(shù)據(jù)的時(shí)候需要知道節(jié)點(diǎn)的xpath的路徑案铺,這里可以使用Chrom瀏覽器,打開開發(fā)者模式梆靖,然后找到需要解析的節(jié)點(diǎn)控汉,右鍵復(fù)制xpath路徑
找到我們想要的xpath路徑后就可以解析到我們想要的數(shù)據(jù)了
// 遍歷其子節(jié)點(diǎn)
NSMutableArray *timesArray = [NSMutableArray array];
[postsParentElement.children enumerateObjectsUsingBlock:^(ONOXMLElement * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"%@", obj.stringValue);
[timesArray addObject:[[obj.stringValue stringByReplacingOccurrencesOfString:@" " withString:@""] stringByReplacingOccurrencesOfString:@"\n" withString:@""]];
}];
for (int i = 0; i < timesArray.count; i++) {
Post *post = [Post new];
post.time = timesArray[i];
// team1
//*[@id="List1_1"]/div/table/tr[1]/td[1]
ONOXMLElement *team1 = [doc firstChildWithXPath:[NSString stringWithFormat:@"http://*[@id=\"List1_%d\"]/div/table/tr[1]/td[1]", i+1]];
post.team1 = team1.stringValue;
//*[@id="List1_1"]/div/table/tr[1]/td[3]
ONOXMLElement *team2 = [doc firstChildWithXPath:[NSString stringWithFormat:@"http://*[@id=\"List1_%d\"]/div/table/tr[1]/td[3]", i+1]];
post.team2 = team2.stringValue;
//*[@id="List1_1"]/div/table/tr[2]/td[1]
ONOXMLElement *score1 = [doc firstChildWithXPath:[NSString stringWithFormat:@"http://*[@id=\"List1_%d\"]/div/table/tr[2]/td[1]", i+1]];
post.score1 = score1.stringValue;
//*[@id="List1_1"]/div/table/tr[2]/td[3]
ONOXMLElement *score2 = [doc firstChildWithXPath:[NSString stringWithFormat:@"http://*[@id=\"List1_%d\"]/div/table/tr[2]/td[3]", i+1]];
post.score2 = score2.stringValue;
//*[@id="List1_1"]/div/table/tr[3]/td/a[1]
ONOXMLElement *link = [doc firstChildWithXPath:[NSString stringWithFormat:@"http://*[@id=\"List1_%d\"]/div/table/tr[3]/td/a[1]", i+1]];
post.link = [link valueForAttribute:@"href"];
[array addObject:post];
}
這里可能會(huì)遇到一個(gè)坑笔诵,就是根據(jù)復(fù)制過來的xpath路徑解析不出來數(shù)據(jù),這個(gè)時(shí)候需要去檢查xpath路徑是否正確姑子,我之前碰到的是//[@id="List1_2"]/div/table/tbody/tr[1]/td[1]/a乎婿,但是真正解析的是//[@id="List1_2"]/div/table/tr[2]/td[1]**,這個(gè)可能需要自己去測(cè)試了吧街佑。
另外對(duì)于CSS的解析方式并沒有去實(shí)現(xiàn)谢翎,有興趣的可以自己去實(shí)現(xiàn)。
本文Demo 鏈接:https://pan.baidu.com/s/11pNP14sZhVTliuP3js_ibA 密碼:abeo