1

问题陈述:我需要使用 SAS 程序从 Web 获取数据并将其放入 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 数据集的输出应该是这样的:

4

3 回答 3

2

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

但是,当 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()某些列
  • 大小合适的字符列
  • 转换他人
    • 字符转数字
    • 迄今为止的字符
于 2020-11-30T21:33:27.417 回答
1

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

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;

结果 在此处输入图像描述

于 2020-11-30T21:33:36.583 回答
1

不幸的是,虽然 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,对于初学者,两者都有很好的解析器可用)很好地集成。

于 2020-12-01T00:15:01.063 回答