请选择 进入手机版 | 继续访问电脑版
楼主: 1989pengwei
16886 20

[原创博文] SAS网络爬虫抓取网页数据 [推广有奖]

  • 0关注
  • 1粉丝

高中生

55%

还不是VIP/贵宾

-

威望
0
论坛币
5 个
通用积分
1.0018
学术水平
4 点
热心指数
4 点
信用等级
4 点
经验
51 点
帖子
8
精华
0
在线时间
56 小时
注册时间
2013-12-8
最后登录
2015-8-19

1989pengwei 发表于 2014-9-23 01:51:17 |显示全部楼层 |坛友微信交流群
相似文件 换一批

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
本人刚刚完成SAS正则表达式的学习,初学SAS网络爬虫,看到过一些前辈大牛们爬虫程序,感觉很有趣。现在结合实际例子,浅谈一下怎么做一些最基本的网页数据抓取。第一次发帖,不妥之处,还望各位大牛们指正。
本帖研究网页为'http://health.gmw.cn/2012-10/03/content_5266132.htm',意在提取该网页中全国各省降雨量信息,部分截图如下: L8_]9SD~K)PD$H[A`0MI_14.png

大致步骤就是用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;
/*...............................................................................................................................................................*/










二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:抓取网页数据 网络爬虫 filename download Content 降雨量 表达式 网络 网页 程序

已有 2 人评分论坛币 学术水平 热心指数 信用等级 收起 理由
玩于股涨之上 + 1 + 1 + 1 精彩帖子
Tigflanker + 5 + 3 + 3 + 3 很感兴趣,感谢分享

总评分: 论坛币 + 5  学术水平 + 4  热心指数 + 4  信用等级 + 4   查看全部评分

本帖被以下文库推荐

  • · MyLib|主题: 409, 订阅: 41
sqy 发表于 2014-9-23 08:35:19 |显示全部楼层 |坛友微信交流群
牛!!!!!!!!!

使用道具

支持哦       
              
                          
                  
                   
                                 
        

使用道具

小鳄鱼a 发表于 2014-9-26 14:51:47 |显示全部楼层 |坛友微信交流群
直接复制粘贴上去了 ,  不行呢

使用道具

小鳄鱼a 发表于 2014-9-26 14:52:23 |显示全部楼层 |坛友微信交流群
  1. /*.............................................................................................................................*/
  2. filename  fileref  url 'http://health.gmw.cn/2012-10/03/content_5266132.htm';
  3. data a;
  4. infile fileref  lrecl=10000  dlm='>' encoding='utf-8' firstobs=174 obs=613;
  5. input text @@;
  6. run;

  7. data newa;
  8. if  _n_=1 then prx=prxparse('/.+</');
  9. retain  prx;/*必须要用retain 否则下次循环时prx置为空值而产生错误*/
  10. set a;
  11. if  prxmatch(prx,text);/*筛选那些不符合正则表达式形式的观测值*/
  12. text=substr(text,1,find(text,'<')-1);/*从合适观测中提取所需数据的字符形式*/
  13. drop prx;
  14. run;  
  15. /*.................................................................................................................................*/

  16. b.源代码文件中每一个input line整体作为一个值,这样就保留了原来形式<...>!!!<...>或者<...><...>,根据>!!!<写出对应表达式进行清洗。考虑用正则表达式'/>.{1,8}</'(数据位数最多为8)。
  17. 此种方式编程如下:
  18. /*................................................................................................................................*/
  19. filename  fileref  url  'http://health.gmw.cn/2012-10/03/content_5266132.htm';
  20. data b;
  21. infile fileref  lrecl=10000  encoding='utf-8'  firstobs=174  obs=613  length=len;
  22. input textvarying1000. len;
  23. run;

  24. data newb;
  25. if _n_=1 then prx=prxparse('/>.{1,8}</');
  26. retain prx;
  27. set b;
  28. call prxsubstr(prx,text,position,length);
  29. if position;
  30. text=substrn(text,position+1,length-2);
  31. keep text;
  32. run;
  33. /*...............................................................................................................................*/
  34. 以上两种方式主要看各位的习惯吧。得到了筛选后的数据集work.newa(work.newb),数据集只含有1个变量text。而网页中则有6个变量。这是就需要对数据集work.newa做写什么了。
  35. 法1.set操作:
  36. /*.................................................................................................................................................................*/
  37. data new;
  38. set newa(rename=(text=text1) firstobs=1);
  39. set newa(rename=(text=text2) firstobs=2);
  40. set newa(rename=(text=text3) firstobs=3);
  41. set newa(rename=(text=text4) firstobs=4);
  42. set newa(rename=(text=text5) firstobs=5);
  43. set newa(rename=(text=text6) firstobs=6);
  44. if not anydigit(text1);
  45. label text1='名称(1)'  text2='人口'  text3='面积'  text4='年降水量'  text5='总降水量' text6='人均降水';
  46. run;
  47. /*.............................................................................................................................................................*/
  48. 注意:为避免重复,上述6个set语句完全可以用宏语句来代替,程序如下:
  49. %macro t(n);
  50. %do i=1 %to &n;
  51. %str(set n(rename=(text=text&i) firstobs=&i);)
  52. %end;
  53. %mend;
  54. data new;
  55. %t(6)
  56. if not anydigit(text1);
  57. label text1='名称(1)'  text2='人口'  text3='面积'  text4='年降水量'  text5='总降水量' text6='人均降水';
  58. run;

  59. 法2.分组transpose:
  60. /*...............................................................................................................................................................*/
  61. data t;
  62. set newa;
  63. f=ceil(_n_/6);/*引入新变量f作为分组变量*/
  64. run;
  65. proc transpose data=t out=new(drop=_name_ f) prefix=text;
  66. var text;
  67. by f;/*由于数据集t中f已经按序排列,故不必再用sort过程*/
  68. label text1='名称(1)' text2='人口' text3='面积' text4='年降水量' text5='总降水量' text6='人均降水';
  69. run;
  70. /*...............................................................................................................................................................*/
复制代码


使用道具

小鳄鱼a 发表于 2014-9-26 14:53:06 |显示全部楼层 |坛友微信交流群
就是复制的上面的,不知道哪个地方有问题

使用道具

1989pengwei 发表于 2014-9-27 12:54:27 |显示全部楼层 |坛友微信交流群
小鳄鱼a 发表于 2014-9-26 14:53
就是复制的上面的,不知道哪个地方有问题
SAS 报错了么?

使用道具

1989pengwei 发表于 2014-9-27 12:59:28 |显示全部楼层 |坛友微信交流群
1989pengwei 发表于 2014-9-27 12:54
SAS 报错了么?
肯定不能全部复制的,从a或b代码中任选一种,再从法一或法二中任选一种即可(你试一下a+法2)

使用道具

just31415 发表于 2014-9-27 23:29:15 |显示全部楼层 |坛友微信交流群
感谢分享,学习了~~

使用道具

很好不错,我前段时间也写了一个,不过网页都是比较简单的get提交那类,楼主能否也写个post提交的,有空一起交流学习下。

使用道具

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群

京ICP备16021002-2号 京B2-20170662号 京公网安备 11010802022788号 论坛法律顾问:王进律师 知识产权保护声明   免责及隐私声明

GMT+8, 2024-4-19 08:10