从网站导入表格到Mathematica中-空单元格问题

7

我使用以下代码从网站中导入数据:
data=Import["http://weburl/","Data"]
在该页面上有表格。这将创建嵌套列表,您可以轻松地以表格形式获取数据。例如:
Grid[data[[1]]]
将会得到类似这样的结果:

Player Age Shots Goals
  P1    24    10    2 
  P2    22     5    0
  P3    28    11    1
  ...

现在,问题就在这里。如果html表格中有一个单元格为空,例如“年龄”条目,则在html中它看起来像这样:<td></td>。Mathematica根本不会将其包含在列表中,甚至不会将其作为“Null”值。相反,该行将仅由长度为3的列表表示,并且数据将移动一列,因此您将得到“射门”代替“年龄”,而“进球”代替“射门”,而“进球”将为空。 例如,一个年龄不详(html表格中的空单元格)的“P4”,他有10次射门和0个进球,将被导入为长度为3的列表,而不是4,并且会向后移一位:

Player Age Shots Goals
  P1    24    10    2 
  P2    22     5    0
  P3    10     0  
  ...

这是一个棘手的问题,因为如果你有几个空字段,则无法从列表中确定它属于哪一列。在将html表导入Mathematica时,是否有一种方法在空单元格上放置“Null”?例如,列表中的P4元素应如下所示:
data[[1,5]]
{"P4","Null",10,0}
而不是:
{"P4",10,0}

1
在 Belisarius 的话中:允许我欢迎您来到 StackOverflow 并提醒以下三点:1)在获得帮助的同时,请试着回答您专业领域的问题。2)阅读常见问题解答(FAQ)。3)当您看到好的问答时,使用灰色三角形将其投票支持,因为该系统的可信度是基于用户通过分享知识而获得的声誉。同时,请记得接受最佳答案,如果有的话,可以通过点击选中标志来解决您的问题。 - Sjoerd C. de Vries
提供一个示例页面进行测试会很有帮助。 - Mr.Wizard
最终我使用了Import["url", "FullData"]//InputForm,这给了我想要的结果。但是我一定会记住你们所有的建议,为我的未来工作做好准备。//InputForm是非常有用的命令。谢谢大家! - enedene
3个回答

9
正如lumeng指出的那样,您可以使用FullData来正确填充HTML表格元素。以下是更简单的说明。
in = ImportString["\<<html><table>
   <tr>
   <td>(1,1)</td>
   <td>(1,2)</td>
   <td>(1,3)</td>
   </tr>
   <tr>
   <td>(2,1)</td>
   <td></td>
   <td>(2,3)</td>
   </tr>
   </table></html>\>",
   {"HTML", "FullData"}];
Grid[in[[1, 1]]]

如果你想更完全地控制输出,我建议你将页面作为XML导入。这是一个例子。

in = ImportString["\<<html><table>
    <tr>
    <td>(1,1)</td>
    <td>(1,2)</td>
    <td>(1,3)</td>
    </tr>
    <tr>
    <td>(2,1)</td>
    <td></td>
    <td>(2,3)</td>
    </tr>
    </table></html>\>", "XML"];
Column[Last /@ Cases[in,
   XMLElement["td", ___], Infinity]]

你需要对XML和Mathematica的版本,特别是XMLObject进行一些阅读。一旦你掌握了它,它是非常好用的。

3
你好,"<...>" 语法在示例字符串中的含义是什么? - WReach
2
@WReach。该格式能够正确识别换行符,因此在输入文本块时通常使用。 - Mark McClure
好的,{"Html","FullData"}可以完成任务,我可以获取所有信息。但是我需要采取另一种方法,“FullData”会完全破坏我使用“Data”获得的良好结构化数据。由于我的页面上有大量变化的表格,这些嵌套列表实在太乱了。因此,我可能会尝试用 <td>Null</td> 替换 <td></td> 和类似的空单元格,然后使用“Data”导入。 - enedene
最终我使用了Import["url", "FullData"]//InputForm,这给了我想要的结果。 但是我一定会记住你们所有的建议,用于我的未来工作。 //InputForm是非常有帮助的命令。 谢谢大家! - enedene

5
In[13]:= htmlcode = "<html><table border=\"1\">
<tr>
<td>row 1, cell 1</td>
<td>row 1, cell 2</td>
<td>row 1, cell 3</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td></td>
<td>row 2, cell 3</td>
</tr>
</table><html>";

In[14]:= file = ToFileName[{$TemporaryDirectory}, "tmp.html"]
Out[14]= "/tmp/tmp.html"


In[15]:= OpenWrite[file]
WriteString[file,htmlcode]
Close[file]
FilePrint[file]
Out[15]= OutputStream[/tmp/tmp.html,18]
Out[17]= /tmp/tmp.html
During evaluation of In[15]:=
<html><table border="1">
<tr>
<td>row 1, cell 1</td>
<td>row 1, cell 2</td>
<td>row 1, cell 3</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td></td>
<td>row 2, cell 3</td>
</tr>
</table><html>
In[23]:= Import[file,"Elements"]//InputForm
Out[23]//InputForm=
{"Data", "FullData", "Hyperlinks", "ImageLinks", "Images", "Plaintext", "Source", "Title", "XMLObject"}
In[22]:= Import[file,"FullData"]//InputForm
Out[22]//InputForm=
{{{{"row 1, cell 1", "row 1, cell 2", "row 1, cell 3"}, {"row 2, cell 1", "", "row 2, cell 3"}}}, {}}

开发者,你在这里想要完成什么?请解释一下这段代码的作用。 - rcollyer
1
据我看,@rcollyer的做法是将一个示例HTML表格写入文件,然后使用Import读取该文件。选项“FullData”用于填充空白处。使用“Put”或“Export”可以更轻松地编写文件。甚至在这个演示中使用文件也是不必要的,因为还有ImportString,它将字符串视为要从中导入的文件。 - Sjoerd C. de Vries
@Sjoerd,我知道它的作用,但我想鼓励“更多解释,少些代码”的方法。在我看来,一大块代码如果没有任何附带说明,基本上是无用的。以其目前的形式,它能够回答问题,但只是在最广泛的意义上,因为它没有提供任何关于解决方案的背景或动机的指导。这就像阅读一个数学证明,没有任何附带文本;它可能是正确的,但几乎不能算可读。 - rcollyer
正如我在Mark McClure的帖子中所说,我将尝试给空单元格赋值“Null”,因为FullData破坏了“Data”的优雅。 因此,我将导入HTML代码,将Null放入空单元格中,然后导入字符串[data,“Data”],应该会得到一个易于阅读的表格。 - enedene

3
利用Computist的示例,您也可以执行以下操作:
htmlcode = "<html><table border=\"1\">
  <tr>
  <td>row 1, cell 1</td>
  <td>row 1, cell 2</td>
  <td>row 1, cell 3</td>
  </tr>
  <tr>
  <td>row 2, cell 1</td>
  <td></td>
  <td>row 2, cell 3</td>
  </tr>
  </table><html>";

StringReplace[htmlcode, "<td></td>" -> "<td>###</td>"];

ImportString[%, "Data"] /. "###" -> Null

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接