iOS开发——网络使用技术OC篇&网络爬虫-使用正则表达式抓取网络数据
网络爬虫-使用正则表达式抓取网络数据
关于网络数据抓取不仅仅在iOS开发中有,其他开发中也有,也叫网络爬虫,大致分为两种方式实现
- 1:正则表达
- 2:利用其他语言的工具包:java/Python
先来看看网络爬虫的基本原理:
一个通用的网络爬虫的框架如图所示:

网络爬虫的基本工作流程如下:
1.首先选取一部分精心挑选的种子URL;
2.将这些URL放入待抓取URL队列;
3.从待抓取URL队列中取出待抓取在URL,解析DNS,并且得到主机的ip,并将URL对应的网页下载下来,存储进已下载网页库中。此外,将这些URL放进已抓取URL队列。
4.分析已抓取URL队列中的URL,分析其中的其他URL,并且将URL放入待抓取URL队列,从而进入下一个循环。
以下内容均为本人个人理解。
网络数据抓取
- 概念:网络数据抓取,也叫网络爬虫。是在我们iOS程序中,获取要抓取到的网页上的数据。
- 用处:如果要用到某网站的一些数据,这个时候我们就要用到抓取数据技术。
- 建议:建议抓取过程中,多利用分类,多写一些分类方法,有助于提高程序可读性,也可提高效率。
今天先来介绍一下第一种:正则表达式
注意点:
其实网络抓取数据很简单,但是有用到正则表达式,这个有人说难,有人说很难,有人说非常难,其实我们抓取数据只会用到“." 、"*"、"?"这三个符号!
正则表达式中:“.”是包括任何字符不包括换行符,“*”是任意多个的字符,“?”是指到最近的一个URL,如果没有就是到最远的一个!
1 NSString *pantten = [NSString stringWithFormat:@"<ul class=\"cs_list\">(.*?)</ul>"];
2
3 NSRegularExpression *regx = [NSRegularExpression regularExpressionWithPattern:pantten options:NSRegularExpressionCaseInsensitive |NSRegularExpressionDotMatchesLineSeparators error:NULL];
其中有两个参数需要大家了解一下,很重要
|
1
2
3
4
5
|
NSRegularExpressionCaseinsensitive 不区分大小写NSRegularExpressionDotMatcheLineSeparators 让“点”字符可以匹配换行符 |
抓数据,其实主要会写匹配字符串就行
- (.*?)表示要抓到的内容
- .*?表示要忽略的内容,爱是啥是啥
- 字符串转义双引号用\转义括号用\\
在开发项目的过程,很多情况下我们需要利用互联网上的一些数据,在这种情况下,我们可能要写一个爬虫来爬我们所需要的数据。一般情况下都是利用正则表达式来匹配Html,获取我们所需要的数据。一般情况下分以下三步。
1、获取网页的html
- 2、利用正则表达式,获取我们所需要的数据
- 3、分析,使用获取到的数据,(例如,保存到数据库)
接下来我们分析代码:
1、获取网页的html
对于一些网页,不需要提交Post提交数据时,我们可以简单的利用NSURL类来获取我们所需要的html,交将其转换中kCFStringEncodingGB_18030_2000格式,解决中文乱码问题。

1 +(NSString*) urlstring:(NSString*)strurl{
2 NSURL *url = [NSURL URLWithString:strurl];
3 NSData *data = [NSData dataWithContentsOfURL:url];
4
5 NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
6 NSString *retStr = [[NSString alloc] initWithData:data encoding:enc];
7
8 //NSLog(@" html = %@",retStr);
9
10 return retStr;
11 }

对于需要Post提交数据的网页,我们可以利用强大的ASIFormDataRequest类来实现,例如:

1 +(void)getPostResult:(NSString*)startqi{
2 ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:[NSURL URLWithString:URLPost]];
3
4 [request setPostValue:startqi forKey:@"startqi"];
5 [request setPostValue:@"20990101001" forKey:@"endqi"];
6 [request setPostValue:@"qihao" forKey:@"searchType"];//网页的中的搜索方式
7 [request startSynchronous];
8
9 NSData* data = [request responseData];
10
11 if (data==nil) {
12 FCLOG(@"has not data");
13 }
14 else{
15 NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);
16 NSString *retStr = [[NSString alloc] initWithData:data encoding:enc];
17 FCLOG(@"html = %@",retStr);
18 }
19 }

这样的话,我们就通过了两种方式获取了我们所需要的html
2、分析html
关于利用正则表达式匹配问题,我又对NSString类扩展了一个方法-(NSMutableArray *)substringByRegular:(NSString *)regular。根据传入的正则表达式,返回所有匹配的数组。

1 @implementation NSString(StringRegular)
2
3
4 -(NSMutableArray *)substringByRegular:(NSString *)regular{
5
6 NSString * reg=regular;
7
8 NSRange r= [self rangeOfString:reg options:NSRegularExpressionSearch];
9
10 NSMutableArray *arr=[NSMutableArray array];
11
12 if (r.length != NSNotFound &&r.length != 0) {
13
14 int i=0;
15
16 while (r.length != NSNotFound &&r.length != 0) {
17
18 FCLOG(@"index = %i regIndex = %d loc = %d",(++i),r.length,r.location);
19
20 NSString* substr = [self substringWithRange:r];
21
22 FCLOG(@"substr = %@",substr);
23
24 [arr addObject:substr];
25
26 NSRange startr=NSMakeRange(r.location+r.length, [self length]-r.location-r.length);
27
28 r=[self rangeOfString:reg options:NSRegularExpressionSearch range:startr];
29 }
30 }
31 return arr;
32 }
33 @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

1 if (arr!=nil&&[arr count]>0) {
2
3 NSString *prereg=@"\\w{11}";
4 NSString *backreg=@"(\\w{2}\\s{0,1}){8}";
5
6 TicketResultService *service=[[TicketResultService alloc] init];
7 [[Sqlite3Helper Instance] openDB];
8 for (NSString *sub in arr) {
9
10 TicketResult* r=[[[TicketResult alloc] init] autorelease];
11
12 NSMutableArray* prearr=[sub substringByRegular:prereg];
13
14 if (prearr!=nil&&[prearr count]>0) {
15 r.sectionID=(NSString*)[prearr objectAtIndex:0];
16 }
17 else{
18 continue;
19 }
20
21 NSMutableArray *backarr=[sub substringByRegular:backreg];
22 if (backarr!=nil&&[backarr count]>0) {
23 r.result=[backarr objectAtIndex:0];
24 }
25 else{
26 continue;
27 }
28
29 if([service isExist:r.sectionID]){
30 continue;
31 }
32
33 r.type=[NSNumber numberWithInt:1];
34
35 [service addModel:r];
36
37 }
38 [[Sqlite3Helper Instance] closeDB];
39
40 [service release];
41 }

以上爬虫才算正式完成,其实,在此之前还有一个第0步,即判断设备目前的网络状态,如果没有联网的就没有必要去爬虫了,因为你也爬不到任何的数据。判断网络状态我是利用Apple官方的一个例子Reachability,网上也有很多关于这个的例子,我就不再细说了,非常感谢网上的各位大牛们提供的很好的办法,让我能更快的写出这些。
iOS开发——网络使用技术OC篇&网络爬虫-使用正则表达式抓取网络数据的更多相关文章
- iOS开发之多线程技术——GCD篇
本篇将从四个方面对iOS开发中GCD的使用进行详尽的讲解: 一.什么是GCD 二.我们为什么要用GCD技术 三.在实际开发中如何使用GCD更好的实现我们的需求 一.Synchronous & ...
- iOS开发之多线程技术—GCD篇
本篇将从四个方面对iOS开发中GCD的使用进行详尽的讲解: 一.什么是GCD 二.我们为什么要用GCD技术 三.在实际开发中如何使用GCD更好的实现我们的需求 一.Synchronous & ...
- iOS开发之多线程技术——NSOperation篇
本篇将从四个方面对iOS开发中使用到的NSOperation技术进行讲解: 一.什么是NSOperation 二.我们为什么使用NSOperation 三.在实际开发中如何使用NSOperation ...
- iOS开发--JS调用原生OC篇
JS调用原生OC篇 方式一(反正我不用) 第一种方式是用JS发起一个假的URL请求,然后利用UIWebView的代理方法拦截这次请求,然后再做相应的处理. 我写了一个简单的HTML网页和一个btn点击 ...
- ios开发——常用经典算法OC篇&冒泡/快速
冒泡排序与快速排序 1.序言 ios开发中涉及到算法的地方还真不多,除非你的应用程序真的非常大,或者你想你的应用程序性能非常好才会去想到关于算法方面的性能优化,而在ios开发中真的能用得到的也就是关于 ...
- iOS开发——高级UI之OC篇&UIdatePicker&UIPickerView简单使用
UIdatePicker&UIPickerView简单使用 /***************************************************************** ...
- iOS开发之多线程技术
本篇争取一篇讲清讲透,依然将通过四大方面清晰的对iOS开发中多线程的用法进行详尽的讲解: 一.什么是多线程 1)多线程执行原理 2)线程与进程 3)多线程的优缺点 二.我们为什么要用多线程编程技术 三 ...
- iOS开发——网络实用技术OC篇&网络爬虫-使用青花瓷抓取网络数据
网络爬虫-使用青花瓷抓取网络数据 由于最近在研究网络爬虫相关技术,刚好看到一篇的的搬了过来! 望谅解..... 写本文的契机主要是前段时间有次用青花瓷抓包有一步忘了,在网上查了半天也没找到写的完整的教 ...
- iOS开发——网络实用技术OC篇&网络爬虫-使用java语言抓取网络数据
网络爬虫-使用java语言抓取网络数据 前提:熟悉java语法(能看懂就行) 准备阶段:从网页中获取html代码 实战阶段:将对应的html代码使用java语言解析出来,最后保存到plist文件 上一 ...
随机推荐
- SSH项目(struts+spring+hibernate)搭建_代码简化
在上篇讲到SSH框架的搭建后,为了有利于随时能熟练的把一个SSH的项目快速的搭建起来,我又进一步对其了解学习,对代码进行了简化,大家相互讨论学习. 为什么要简化: 如果要做一个大项目,假设项目的ac ...
- tmpfs介绍
tmpfs 前几天发现服务器的内存(ram)和swap使用率非常低,于是就想这么多的资源不用岂不浪费了?google了一下,认识了tmpfs,总的来说tmpfs是一种虚拟内存文件系统正如这个定义它最大 ...
- ftp 服务器搭建和添加用户和目录
安装: yum install -y vsftpd 修改配置: vsftpd.conf 修改:anonymous_enable=YES 改为:anonymous_enable=NO 启动/停止/重启 ...
- Linq学习工具及Lamada表达式
好东西.转载一个.以备学习 Linq学习工具: http://www.linqpad.net/ Lamada表达式: Func<int, int, int> IntPow = (x ...
- Refresh recovery area usage data after manually deleting files under recovery area
Original source: http://www.dba-oracle.com/t_v$_flash_recovery_area.htm If you manually delete files ...
- 第51讲:Scala中链式调用风格的实现代码实战及其在Spark编程中的广泛运用
今天学习了下scala中的链式调用风格的实现,在spark编程中,我们经常会看到如下一段代码: sc.textFile("hdfs://......").flatMap(_.spl ...
- andriod studio
初衷:使用andriod的webview调用html页面,生成app. AVD注意细节: RAM : 1G VM heap:228MB Graphics:software - GLES 2.0 存在的 ...
- 字符串混淆技术在.NET程序保护中的应用及如何解密被混淆的字符串
Visual Studio提供的Dotfuscator保护程序,可以对用户代码中包含的字符串进行加密.比如下面的例子,为了找到这个程序的注册算法,用.NET Reflector加载程序集后,发现代码中 ...
- Linux修改环境变量的方法
在Linux操作系统中,有时候跟着教程安装了一些软件,安装成功后,很高兴的准备运行该软件相应命令,但是偶尔会遇到”Command not found…“的提示.原因是因为你安装的软件需要设置环境变量才 ...
- RCP中如何使用代码安装、运行plugins
其实在google或者http://www.eclipse.org/forums/就能够找到这个问题的答案. 搜索关键字:rcp install plugins\bundles programmati ...