ObjC利用正则表达式抓取网页内容(网络爬虫)

news/2024/7/19 11:21:00 标签: 爬虫, 数据库, php

本文转载至 http://www.cocoachina.com/bbs/read.php?tid=103813&fpage=63

  在开发项目的过程,很多情况下我们需要利用互联网上的一些数据,在这种情况下,我们可能要写一个爬虫来爬我们所需要的数据。一般情况下都是利用正则表达式来匹配Html,获取我们所需要的数据。一般情况下分以下三步。

1、获取网页的html

2、利用正则表达式,获取我们所需要的数据

3、分析,使用获取到的数据,(例如,保存到数据库

接下来我们分析代码:

1、获取网页的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类来实现,例如:

+(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

2、分析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];

3、分析或利用数据,在这里,我只是利用上一篇博客上所述方法简单的把这些数据保存到了数据库(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,网上也有很多关于这个的例子,我就不再细说了,非常感谢网上的各位大牛们提供的很好的办法,让我能更快的写出这些。

转载于:https://www.cnblogs.com/Camier-myNiuer/p/3488563.html


http://www.niftyadmin.cn/n/813655.html

相关文章

如何改进iOS App的离线使用体验

本问转载至 http://www.cnblogs.com/wangkewei/archive/2012/10/10/2718641.html#2838501 App Store中的App分析 App已经与我们形影不离了&#xff0c;不管在地铁上、公交上还是在会场你总能看到很多人拿出来手机&#xff0c;刷一刷微博&#xff0c;看看新闻。 据不完全统计有近…

ZooKeeper系列(二)

Zookeeper的环境配置 一、Zookeeper的搭建方式 Zookeeper安装方式有三种&#xff0c;单机模式和集群模式以及伪集群模式。 1.单机模式&#xff1a;Zookeeper只运行在一台服务器上&#xff0c;适合测试环境&#xff1b; 2.伪集群模式&#xff1a;就是在一台物理机上运行多个Zook…

【数据库】【JDBC】使用JDBC进行批处理

在实际的项目开发中&#xff0c;有时候需要向数据库发送一批SQL语句执行&#xff0c;这时应避免向数据库一条条的发送执行&#xff0c;而应采用JDBC的批处理机制&#xff0c;以提升执行效率。   JDBC实现批处理有两种方式&#xff1a;statement和preparedstatement 一、使用S…

ZooKeeper系列(三)

前面虽然配置了集群模式的Zookeeper&#xff0c;但是为了方面学建议在伪分布式模式的Zookeeper学习Zookeeper的shell命令。 一、Zookeeper的四字命令 Zookeeper支持某些特定的四字命令字母与其的交互。他们大多数是查询命令&#xff0c;用来获取Zookeeper服务的当前状态及相关信…

ZooKeeper系列(四)

一、配置服务 配置服务是分布式应用所需要的基本服务之一&#xff0c;它使集群中的机器可以共享配置信息中那些公共的部分。简单地说&#xff0c;ZooKeeper可以作为一个具有高可用性的配置存储器&#xff0c;允许分布式应用的参与者检索和更新配置文件。使用ZooKeeper中的观察机…

【数据库】【JDBC】使用JDBC处理Oracle大数据

JavaWeb学习总结(三十五)——使用JDBC处理Oracle大数据 一、Oracle中大数据处理 在Oracle中&#xff0c;LOB&#xff08;Large Object&#xff0c;大型对象&#xff09;类型的字段现在用得越来越多了。因为这种类型的字段&#xff0c;容量大&#xff08;最多能容纳4GB的数据&am…

程序员面试、算法研究、编程艺术、红黑树、数据挖掘5大经典原创系列集锦与总结...

作者&#xff1a;July--结构之法算法之道blog之博主。时间&#xff1a;2010年10月-2013年10月。出处&#xff1a;http://blog.csdn.net/v_JULY_v 。声明&#xff1a;版权所有&#xff0c;侵犯必究。 感谢博主的硕果 前言 开博刚好3周年&#xff0c;回首这3年&#xff0c;发…

iOS 消息推送原理及实现Demo

本文转载至 http://www.cnblogs.com/cdts_change/p/3240893.html 一、消息推送原理&#xff1a; 在实现消息推送之前先提及几个于推送相关概念&#xff0c;如下图1-1&#xff1a; 1、Provider&#xff1a;就是为指定IOS设备应用程序提供Push的服务器&#xff0c;&#xff08;如…