在開發項目的過程,不少狀況下咱們須要利用互聯網上的一些數據,在這種狀況下,咱們可能要寫一個爬蟲來爬咱們所須要的數據。通常狀況下都是利用正則表達式來匹配Html,獲取咱們所須要的數據。通常狀況下分如下三步:
一、獲取網頁的html
二、利用正則表達式,獲取咱們所須要的數據
三、分析,使用獲取到的數據,(例如,保存到數據庫)html
接下來咱們分析代碼:
一、獲取網頁的html
對於一些網頁,不須要提交Post提交數據時,咱們能夠簡單的利用NSURL類來獲取咱們所須要的html,交將其轉換中kCFStringEncodingGB_18030_2000格式,解決中文亂碼問題。正則表達式
+(NSString*) urlstring:(NSString*)strurl{
NSURL *url = [NSURL URLWithString:strurl];
NSData *data = [NSData dataWithContentsOfURL:url];
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSString *retStr = [[NSString alloc] initWithData:data encoding:enc];
//NSLog(@" html = %@",retStr);
return retStr;
}
對於須要Post提交數據的網頁,咱們能夠利用強大的ASIFormDataRequest類來實現,例如:sql
+(void)getPostResult:(NSString*)startqi{
ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:[NSURL URLWithString:URLPost]];
[request setPostValue:startqi forKey:@"startqi"];
[request setPostValue:@"20990101001" forKey:@"endqi"];
[request setPostValue:@"qihao" forKey:@"searchType"];//網頁的中的搜索方式
[request startSynchronous];
NSData* data = [request responseData];
if (data==nil) {
FCLOG(@"has not data");
}
else{
NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
NSString *retStr = [[NSString alloc] initWithData:data encoding:enc];
FCLOG(@"html = %@",retStr);
}
}
這樣的話,咱們就經過了兩種方式獲取了咱們所須要的html數據庫
二、分析html
關於利用正則表達式匹配問題,我又對NSString類擴展了一個方法-(NSMutableArray *)substringByRegular:(NSString *)regular。根據傳入的正則表達式,返回全部匹配的數組。數組
@implementation NSString(StringRegular)
-(NSMutableArray *)substringByRegular:(NSString *)regular{
NSString * reg=regular;
NSRange r= [self rangeOfString:reg options:NSRegularExpressionSearch];
NSMutableArray *arr=[NSMutableArray array];
if (r.length != NSNotFound &&r.length != 0) {
int i=0;
while (r.length != NSNotFound &&r.length != 0) {
FCLOG(@"index = %i regIndex = %d loc = %d",(++i),r.length,r.location);
NSString* substr = [self substringWithRange:r];
FCLOG(@"substr = %@",substr);
[arr addObject:substr];
NSRange startr=NSMakeRange(r.location+r.length, [self length]-r.location-r.length);
r=[self rangeOfString:reg options:NSRegularExpressionSearch range:startr];
}
}
return arr;
}
@end
在這種狀況下,咱們首先我獲得咱們要獲取數據的正則表達式,關於正則表達式這種火星文我就很少說了,我也很糾結,我就很少說了,可是有一點就是,所寫的正則表達式必定是咱們所須要的數據,而且可以屏蔽無效信息的,有可能在一次匹配中沒法獲取,能夠屢次利用正則表達式來分段獲取。下面是個人語句,在個人例子中,就是兩次利用正則表達式。網絡
NSString *regstr = @"<td class=\'z_bg_05\'>\\w{11}</td><td class=\'z_bg_13\'>(\\w{2}\\s{0,1})*</td>";
NSMutableArray *arr=[strhtml substringByRegular:regstr];
三、分析或利用數據,在這裏,我只是利用上一篇博客上所述方法簡單的把這些數據保存到了數據庫(sqlite3)中。
其實在這個arr數組中一條就是對應我數據庫表中的一條記錄,可是像td class等這些信息我是不須要的,因此再次利用正則表達式來分析NSString工具
if (arr!=nil&&[arr count]>0) {
NSString *prereg=@"\\w{11}";
NSString *backreg=@"(\\w{2}\\s{0,1}){8}";
TicketResultService *service=[[TicketResultService alloc] init];
[[Sqlite3Helper Instance] openDB];
for (NSString *sub in arr) {
TicketResult* r=[[[TicketResult alloc] init] autorelease];
NSMutableArray* prearr=[sub substringByRegular:prereg];
if (prearr!=nil&&[prearr count]>0) {
r.sectionID=(NSString*)[prearr objectAtIndex:0];
}
else{
continue;
}
NSMutableArray *backarr=[sub substringByRegular:backreg];
if (backarr!=nil&&[backarr count]>0) {
r.result=[backarr objectAtIndex:0];
}
else{
continue;
}
if([service isExist:r.sectionID]){
continue;
}
r.type=[NSNumber numberWithInt:1];
[service addModel:r];
}
[[Sqlite3Helper Instance] closeDB];
[service release];
}
以上爬蟲纔算正式完成,其實,在此以前還有一個第0步,即判斷設備目前的網絡狀態,若是沒有聯網的就沒有必要去爬蟲了,由於你也爬不到任何的數據。判斷網絡狀態我是利用Apple官方的一個例子Reachability,網上也有不少關於這個的例子,我就再也不細說了,很是感謝網上的各位大牛們提供的很好的辦法,讓我能更快的寫出這些。url
本博主有mac os用的正則表達式檢測工具以及源碼(即reginald正則檢查工具以及源碼),須要的能夠給我留言/評論