本帖研究网页为'http://health.gmw.cn/2012-10/03/content_5266132.htm',意在提取该网页中全国各省降雨量信息,部分截图如下:
大致步骤就是用filename fileref url '网页地址'获取网页代码信息(包含有待提取数据),再用infile fileref将字符代码读入变量中,接着根据待提取数据的特点对写入的观测进行“数据清洗”,最后获得所需数据观测。
先针对该过程中可能出现的问题,做一下简单说明:
1.本人所用SAS软件为多国语言9.2版,刚开始运行含有filename fileref url '网页地址'及infile fileref时,很不友好的显示错误:无法连接主机。这一问题困惑我好久。最后看到有前辈发帖,从一个网站http://ftp.sas.com/techsup/download/hotfix/f9_sbcs_prod_list.html#034098下载相关hot fix(F9BA26)以后,得以解决。
2.若未在infile语句中加encoding='utf-8',得出的观测乱码。
3.正则表达式并不是必须的,但是用起来简洁明了,与一些字符函数配合使用,绝对可以达到你想要的提取目的。
4.大家进入网页后,点击右键,查看源代码(有些是源文件),这个源代码就是我们需要写入数据集的文件。先用
filename fileref url 'http://health.gmw.cn/2012-10/03/content_5266132.htm';
5.怎样将网页源文件代码写入数据集?用infile+input。不过根据写入方式不同,后续清洗数据的程序自然也不一样了。由于源代码中每一个input line的形式为<...>!!!<...>或者<...><...>(大家可以观察网页的源代码),而我们需要的数据就包含在!!!里面。而由于一个网页包含的信息太多,也有可能找到的!!!不包含所需数据。为了“清洗”数据方便,在这里我采用了一个比较笨的方法,通过观察源代码中待提取数据的大致范围,如第一个待提取字符串"黑龙江"出现在第184个input line,而最后一个"120”(澳门人均降水) 则出现在第623个input line,其他input line我们不需要,可以考虑在infile语句中加入firstobs=184 obs=623。
注意:由于网页可能发生小的变化,firstobs=与obs= 的值可能不准确,从而影响结果。建议查看源代码确定相应值。
这里介绍两种不同的写入方式。
a.以'>'为分隔符,写入后每个观测就形如<...或者!!!<...,而后者是我们所需保留的观测。根据!!!<...写出对应正则表达式进行清洗。考虑用正则表达式'/.+/'。
此种方式编程如下:
/*.............................................................................................................................*/
filename fileref url 'http://health.gmw.cn/2012-10/03/content_5266132.htm';
data a;
infile fileref lrecl=10000 dlm='>' encoding='utf-8' firstobs=184 obs=623;
length text $1000;
input text $ @@;
run;
data newa;
if _n_=1 then prx=prxparse('/.+</');
retain prx;/*必须要用retain 否则下次循环时prx置为空值而产生错误*/
set a;
if prxmatch(prx,text);/*筛选那些不符合正则表达式形式的观测值*/
text=substr(text,1,find(text,'<')-1);/*从合适观测中提取所需数据的字符形式*/
drop prx;
run;
/*.................................................................................................................................*/
b.源代码文件中每一个input line整体作为一个值,这样就保留了原来形式<...>!!!<...>或者<...><...>,根据>!!!<写出对应表达式进行清洗。考虑用正则表达式'/>.{1,8}</'(数据位数最多为8)。
此种方式编程如下:
/*................................................................................................................................*/
filename fileref url 'http://health.gmw.cn/2012-10/03/content_5266132.htm';
data b;
infile fileref lrecl=10000 encoding='utf-8' firstobs=184 obs=623 length=len;
input text $varying1000. len;
run;
data newb;
if _n_=1 then prx=prxparse('/>.{1,8}</');
retain prx;
set b;
call prxsubstr(prx,text,position,length);
if position;
text=substrn(text,position+1,length-2);
keep text;
run;
/*...............................................................................................................................*/
以上两种方式主要看各位的习惯吧。得到了筛选后的数据集work.newa(work.newb),数据集只含有1个变量text。而网页中则有6个变量。这是就需要对数据集work.newa做写什么了。
法1.set操作:
/*.................................................................................................................................................................*/
data new;
set newa(rename=(text=text1) firstobs=1);
set newa(rename=(text=text2) firstobs=2);
set newa(rename=(text=text3) firstobs=3);
set newa(rename=(text=text4) firstobs=4);
set newa(rename=(text=text5) firstobs=5);
set newa(rename=(text=text6) firstobs=6);
if not anydigit(text1);
label text1='名称(1)' text2='人口' text3='面积' text4='年降水量' text5='总降水量' text6='人均降水';
run;
/*.............................................................................................................................................................*/
注意:为避免重复,上述6个set语句完全可以用宏语句来代替,程序如下:
%macro t(n);
%do i=1 %to &n;
%str(set n(rename=(text=text&i) firstobs=&i);)
%end;
%mend;
data new;
%t(6)
if not anydigit(text1);
label text1='名称(1)' text2='人口' text3='面积' text4='年降水量' text5='总降水量' text6='人均降水';
run;
法2.分组transpose:
/*...............................................................................................................................................................*/
data t;
set newa;
f=ceil(_n_/6);/*引入新变量f作为分组变量*/
run;
proc transpose data=t out=new(drop=_name_ f) prefix=text;
var text;
by f;/*由于数据集t中f已经按序排列,故不必再用sort过程*/
label text1='名称(1)' text2='人口' text3='面积' text4='年降水量' text5='总降水量' text6='人均降水';
run;
/*...............................................................................................................................................................*/



雷达卡




京公网安备 11010802022788号







