最近公司有一個需求,需要從某網頁上獲取一些數據傳給后臺。那就是通過固定網址下載html網頁源代碼,然后解析。
我先說下解析的庫是Ono,他的作者是mattt,也是AFNetworking的貢獻者。
Ono非常小,如果是不用CocoaPods添加的話也只需加入ONOXMLDocument.h和ONOXMLDocument.m兩個文件就好了,不過還要導入libxml2系統自帶的庫,在Build Setting-Header Search Paths中加入 "/usr/include/libxml2"路徑。(后有截圖)
當然如果使用CocoaPods的話就:
pod 'Ono'
Ono庫可以單獨使用也可以配合AFNetworking一起用。
解析完整過程
這里的url是中國商品信息服務平臺的查詢接口。
首先獲取html:
NSString *urlstring = [NSString stringWithFormat:@"http://search.anccnet.com/searchResult2.aspx?keyword=%@",string];
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlstring] options:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000) error:nil];
url中的string是商品條形碼的數字(當然也可以是商品名)。
CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000)
這是網頁的編碼格式,一般中國網站的編碼格式都是gb2312,當然這也能在html頭信息中看到(下面會講到)。
具體內容你可以用chrome、firefox等瀏覽器打開看下源代碼。你也可以用:
NSString *appConnect = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlstring] encoding:CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000) error:nil];
然后輸出字符串查看具體內容。因為內容較多,我就把需要中到的內容展示出來(不需要的內容我刪掉了):
<!DOCTYPE html>
<html>
<head>
<meta charset="gb2312" />
</head>
<body >
<form name="form1" method="post" action="searchResult2.aspx?keyword=6949322340125" id="form1">
<div class="wrap">
<div class="bodyer">
<div class="mainly">
<div id="outter">
<ol id="results">
<li>
<div class="result">
<p class="p-img" align="center"><a id="repList_ctl00_herl" target="_blank"> </a></p>
<dl class="p-supplier">
<dt>商標:</dt>
<dd>惠松</dd>
<dt>發布廠家:</dt>
<dd>
<a id="repList_ctl00_firmLink" target="_blank">浙江惠松制藥有限公司</a>
</dd>
</dl>
<dl class="p-info">
<dt>商品條碼:</dt>
<dd><a target="_blank">06949322340125</a></dd>
<dt>名稱:</dt>
<dd> 復方魚腥草合劑</dd>
<dt>規格型號:</dt>
<dd> 10ML12憑</dd>
<dt>描述:</dt>
<dd> </dd>
</dl>
<br clear="all" />
</div>
</li>
</ol>
</div>
</div>
<div id="myPager">
</div>
</div>
</div>
</html>
html的內容我就不解釋了,可以在w3school 中查看。
可以看到頭部中有顯示是gb2312編碼格式。我要獲取到的就是其中商品的一些信息(包括商品條碼、名稱、規格型號、描述、商標和發布廠商)。
下面是解析的代碼:
ONOXMLDocument *document = [ONOXMLDocument HTMLDocumentWithData:data error:nil];
HTMLMedicine *medicine = [[HTMLMedicine alloc] init];
NSString *xpath = @"http://body/form/div[@class='wrap']/div[@class='bodyer']/div[@class='mainly']/div[@id='outter']/ol[@id='results']/li[1]/div[@class='result']";
[document enumerateElementsWithXPath:xpath usingBlock:^(ONOXMLElement *element, NSUInteger idx, BOOL *stop) {
NSLog(@"%@: %@", element.tag, element.attributes);
for (ONOXMLElement *celement in element.children) {
//商家和發布廠家
if ([celement.tag isEqualToString:@"dl"] && [celement.attributes[@"class"] isEqualToString:@"p-supplier"]) {
NSInteger i = 0;
for (ONOXMLElement *ccelement in celement.children) {
if ([ccelement.tag isEqualToString:@"dd"] && i == 0) {
medicine.brand = [ccelement stringValue];
i++;
}
else if ([ccelement.tag isEqualToString:@"dd"] && i == 1) {
medicine.manufacturer = [[ccelement stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
}
}
//商品條碼、名稱、規格型號、描述
if ([celement.tag isEqualToString:@"dl"] && [celement.attributes[@"class"] isEqualToString:@"p-info"]) {
NSInteger i = 0;
for (ONOXMLElement *ccelement in celement.children) {
if ([ccelement.tag isEqualToString:@"dd"] && i == 0) {
medicine.code = [ccelement stringValue];
i++;
}
else if ([ccelement.tag isEqualToString:@"dd"] && i == 1) {
medicine.name = [ccelement stringValue];
i++;
}
else if ([ccelement.tag isEqualToString:@"dd"] && i == 2) {
medicine.specificagionmodel = [ccelement stringValue];
i++;
}
else if ([ccelement.tag isEqualToString:@"dd"] && i == 3) {
medicine.descriptions = [ccelement stringValue];
}
}
}
}
NSLog(@"%@",medicine);
}];
首先把NSData轉成ONOXMLDocument,然后定位到你需要的信息位置(用xpath),定位到后得到相應的ONOXMLElement,其中的tag表示節點是什么,attributes是節點中的內容,其它屬性可以自己查看Ono。
具體的解析我就不講了,這里我建了個HTMLMedicine的模型存儲,包含以下屬性:
@property (nonatomic, strong) NSString *code; //商品條碼
@property (nonatomic, strong) NSString *name; //名稱
@property (nonatomic, strong) NSString *specificagionmodel; //規格型號
@property (nonatomic, strong) NSString *descriptions; //描述
@property (nonatomic, strong) NSString *brand; //商標
@property (nonatomic, strong) NSString *manufacturer; //發布廠商
如果你的項目有集成AFNetworking這里也有個便捷的使用方式。
最后是Ono手動集成配置的截圖,感謝閱讀:)