【问题标题】:How to scrape data from a web page using SAS如何使用 SAS 从网页中抓取数据
【发布时间】:2020-11-30 19:33:31
【问题描述】:

问题陈述: 我需要使用 SAS 程序从网络获取数据并将其放入 SAS 数据集。

运行良好: 我可以通过 SAS 获取目标网页的内容。

不工作(需要帮助): 我无法通过 SAS 处理页面的源内容(如下所示)。 我需要在源内容中找到“类别”,如果找到,则获取该行的所有值(NOV、OCT、SEP、AUG、JUL)。 同样,我需要在源内容中找到“会议板”,如果找到,则获取该行的所有值(96.1,101.4,101.3,86.3,91.7)。 源内容结构应始终保持不变。预期输出附加为 png 图像。 如果有人知道并帮助我如何使用 SAS 程序解决这种情况,那将是一个很好的学习和帮助。

我尝试过这样的事情:

filename output "/desktop/Response.txt";

proc http           
url="http://hosting.briefing.com/cschwab/Calendars/EconomicReleases/conf.htm"       
method="get"        
proxyhost="&proxy_host."        
proxyport=&port         
out=output;     
run;

DATA CHECK;
LENGTH CATEGORY $ 5;
RETAIN CATEGORY;
INFILE output LENGTH = recLen LRECL = 32767;
INPUT line $VARYING32767. recLen;
IF FIND(line,'Category') GT 0 THEN DO;
CATEGORY = SCAN(STRIP(line),2,'<>');
OUTPUT;
END;
RUN;

网页的来源内容:

<table width="100%" cellpadding="2" cellspacing="0" border="0">
  <tr valign="top" align="right" class="sectionColor">
    <td class="rH" align="left">Category</td>
    <td class="rH">NOV</td>
    <td class="rH">OCT</td>
    <td class="rH">SEP</td>
    <td class="rH">AUG</td>
    <td class="rH">JUL</td>
  </tr>
  <tr valign="top" align="right" class="sectionColor">
    <td class="rD" align="left">Conference Board</td>
    <td class="rD">96.1</td>
    <td class="rD">101.4</td>
    <td class="rD">101.3</td>
    <td class="rD">86.3</td>
    <td class="rD">91.7</td>
  </tr>
 <tr valign="top" align="right" class="sectionColor">
    <td class="rL" align="left">&nbsp;&nbsp;Expectations</td>
    <td class="rL">89.5</td>
    <td class="rL">98.2</td>
    <td class="rL">102.9</td>
    <td class="rL">86.6</td>
    <td class="rL">88.9</td>
  </tr>
  <tr valign="top" align="right" class="sectionColor">
    <td class="rD" align="left">&nbsp;&nbsp;Present Situation</td>
    <td class="rD">105.9</td>
    <td class="rD">106.2</td>
    <td class="rD">98.9</td>
    <td class="rD">85.8</td>
    <td class="rD">95.9</td>
  </tr>
  <tr valign="top" align="right" class="sectionColor">
    <td class="rL" align="left">Employment  ('plentiful' less 'hard to get')</td>
    <td class="rL">7.2</td>
    <td class="rL">7.1</td>
    <td class="rL">3.3</td>
    <td class="rL">-2.2</td>
    <td class="rL">2.2</td>
  </tr>
  <tr valign="top" align="right" class="sectionColor">
    <td class="rD" align="left">1 yr inflation expectations</td>
    <td class="rD">5.7%</td>
    <td class="rD">5.6%</td>
    <td class="rD">5.7%</td>
    <td class="rD">5.8%</td>
    <td class="rD">6.1%</td>
  </tr>
</table>

SAS 数据集的输出应该是这样的:

【问题讨论】:

  • 您缺少预期的输出。请包含您迄今为止尝试解析该文件的所有代码。

标签: html sas data-science html-parsing data-scrubbing


【解决方案1】:

对于大多数抓取,您希望使用解析库或表格抓取工具。

但是,当 html 可以被依赖为高度规则或模式时,可以使用简单的文本处理。

例子:

filename output temp;

proc http           
url="http://hosting.briefing.com/cschwab/Calendars/EconomicReleases/conf.htm"       
method="get"        
/*proxyhost="&proxy_host."        */
/*proxyport=&port         */
out=output;     
run;

data have_cells (keep=row_num name value);
  length name value $32;

  infile output _infile_=line;
  input;

  retain landmark_found 0 table_found 0 naming 1 in_row 0 row_num -1;

  if not landmark_found then  
    landmark_found = prxmatch('/Highlights/',  line);

  if not landmark_found then
    delete;

  if not table_found then
    table_found = prxmatch('/<table /', line);

  if not table_found then
    delete;

  array names(20) $8 _temporary_;

  if not in_row then
    if prxmatch('/<tr /', line) then do;
      col_index = 0;
      in_row = 1;
      row_num + 1;
      return;
    end;

  if not in_row then
    delete;
td:
  rxtd = prxparse('/<td .*?>(.*)<\/td>/');
  if prxmatch(rxtd, line) then do;
    col_index + 1;
    if naming then do;
      names(col_index) = prxposn(rxtd,1,line);
    end;
    else do;
      name = names(col_index);
      value = prxposn(rxtd,1,line);
      OUTPUT;
    end;
    return;
  end;

  in_row = not prxmatch('/<\/tr/', line);

  if naming then if not in_row then naming = 0;

  if prxmatch('/<\/table>/', line) then stop;
run;

proc transpose data=have_cells out=have_raw;
  by row_num;
  id name;
  var value;
run;

你必须执行更多的编码来

  • htmldecode()某些列
  • 正确大小的字符列
  • 转换他人
    • 字符转数字
    • 至今为止的字符

【讨论】:

  • 太棒了!这是工作。谢谢理查德!!
【解决方案2】:

如果(如果使用 HTML 页面,那是一个很大的问题)文件保持与该示例一样整洁,您可以很容易地解析它。只需查找&lt;table&gt;&lt;tr&gt;&lt;td&gt; 标签。为表号、行号、列号制作自己的计数器。

filename output url 
  "http://hosting.briefing.com/cschwab/Calendars/EconomicReleases/conf.htm"
;

data tall;
 length table row col 8 value $200;
 infile output truncover ;
 do until(left(_infile_)=:'<table'); input ; end;
 table+1;
 row=0;
 do until(left(_infile_)=:'</table');
   input;
   if left(_infile_)=:'<tr' then do; row+1; col=0; end;
   if left(_infile_)=:'<td' then do; 
      value = left(scan(_infile_,-2,'<>')); 
      col+1; 
      if value ne ' ' then output; 
   end;
 end;
run;

然后使用 PROC TRANSPOSE 制作一个矩形结构。看起来你可能不想要第一个表。

proc transpose data=tall out=tables(drop=_name_) prefix=col;
  where table=2;
  by table row;
  id col;
  var value;
run;

但您可能想要转置它。所以在 PROC TRANSPOSE 步骤之前重新排序。

proc sort data=tall;
  by table col row;
run;
proc transpose data=tall out=tables(drop=_name_) prefix=col;
  where table=2;
  by table col;
  id row;
  var value;
run;

结果

【讨论】:

  • Tom,代码很清晰!它工作得很好!非常感谢!
【解决方案3】:

不幸的是,尽管 SAS 没有绝对最佳的 HMTL 解析选项,但您确实有一些选项可以从头开始解析它。

首先,有时您可以像对待 XML 一样对待格式良好的 HTML。你的结构很好,几乎可以做到这一点;唯一的问题是开头缺少标签,这很容易解决。

执行此操作的最佳方法通常是将文本复制到文件中,然后打开 SAS XML Mapper 实用程序。这将使您获得日志消息,让您知道它有什么问题,以便您可以修复它。

一旦你解决了任何小问题,你就可以简单地使用:

filename xml_file '<your html-as-xml file path>';

filename map temp;
  
libname xml_file xmlv2 automap=replace xmlmap=map;

然后可以使用该映射来进一步解析文档。这为您提供了一个库名称“xml_file”,然后它具有成员“table”、“tr”和“td”,您可以使用序数(基本上是自动递增的索引值)将它们相互关联。

在大多数情况下,我建议您的第二个选择是将解析外包给其他语言。 Python 有一个很棒的解析器 BeautifulSoup,它在 SAS 9.4 TS1M6 中可以通过 FCMP 引擎从 SAS 内部使用;或者,如果您熟悉 Groovy,PROC GROOVY 也非常擅长解析 HTML。您可以用另一种语言编写单独的程序,也可以集成它们; SAS 与多种语言(Python 和 R,对于初学者,两者都有很好的解析器可用)很好地集成。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多