使用Mathematica从HTML中提取信息

C. *_* E. 18 wolfram-mathematica

有没有一种简单的方法可以使用Mathematica从特定的HTML表中提取数据? Import似乎非常强大,Mathematica似乎能够很好地处理XML等格式.

这是一个例子:http://en.wikipedia.org/wiki/Unemployment_by_country

Mik*_*rch 13

对于这方面的一般例子,有这些如何:

对于此特定示例,只需导入它

tmp = Import["http://en.wikipedia.org/wiki/Unemployment_by_country", "Data"]
Run Code Online (Sandbox Code Playgroud)

通过此导入清理它是相当简单的.该表是3列,因此从其余的东西中提取它:

tmp1 = Cases[tmp, {_, _?NumberQ, _}, \[Infinity]]
Run Code Online (Sandbox Code Playgroud)

您可能想要删除方括号引用(??):

tmp1[[All, 3]] = Flatten[If[StringQ[#], 
StringCases[#, x__ ~~ Whitespace ~~ "[" ~~ __ :> x], #] & /@ tmp1[[All, 3]]]

Grid[tmp1, Frame -> All]
Run Code Online (Sandbox Code Playgroud)

另请注意,如果您希望在表格中添加标题,则可以将其添加回来

Grid[Join[{{"Country / Region", "Unemployment rate (%)", 
   "Source / date of information"}}, tmp1], Frame -> All]
Run Code Online (Sandbox Code Playgroud)

纯粹主义者可能会反对最后一步,但是当你正在抓取数据时,你只想完成工作,每个网站都是个案前景.因此,一些手动检查和灵活性可以使您获得最快的整体效果

编辑

如果你想要旗帜,你也可以从中得到它们CountryData.需要进行一些进一步的清理,否则会发生很多未命中.清理涉及删除括号中对"主权国家"的引用.例如"关岛(美国)" - >"高卢".

tmp2 = Flatten[
  If[StringMatchQ[#, __ ~~ "(" ~~ __], 
     StringCases[#, 
      z__ ~~ Shortest["(" ~~ __ ~~ ")" ~~ EndOfString] :> 
       StringTrim@z], StringTrim[#]] & /@ tmp1[[All, 1]]]
Run Code Online (Sandbox Code Playgroud)

这仍然会产生一些CountryData无法识别的输出.

flags = CountryData[#, "Flag"] & /@ tmp2;
Cases[flags, _CountryData]
Run Code Online (Sandbox Code Playgroud)

190失误.从输出中删除这些失误:

flags = If[Head[#] === CountryData, {""}, {#}] & /@ flags; (*much faster than rule replacement*)
tmp2 = Join[flags, tmp1, 2];
Grid[tmp2, Frame -> All]
Run Code Online (Sandbox Code Playgroud)

请注意,渲染需要一段时间.

在此输入图像描述

显然,您可以Grid根据需要使用Grid选项设置样式,并在需要时调整图像大小.


Leo*_*rin 6

虽然使用Import可能是一种更好,更健壮的方式,但我发现,至少对于这个特定的问题,我自己的HTML解析器(在这个帖子中发布),只需少量的后期处理就可以正常工作.如果你从那里获取代码并执行它,用这个函数扩充它:

Clear[findAndParseTables];
findAndParseTables[text_String] :=
  Module[{parsed = postProcess@parseText[text]},
    DeleteCases[
      Cases[parsed, _tableContainer, Infinity],
      _attribContainer | _spanContainer, Infinity
    ] //.
    {(supContainer | tdContainer | trContainer | thContainer)[x___] :> {x},
        iContainer[x___] :> x,
        aContainer[x_] :> x,
        "\n" :> Sequence[],
       divContainer[] | ulContainer[] | liContainer[] | aContainer[] :> Sequence[]}];
Run Code Online (Sandbox Code Playgroud)

然后,我认为,通过此代码可以获得非常完整的数据:

text = Import["http://en.wikipedia.org/wiki/Unemployment_by_country", "Text"];
myData = First@findAndParseTables[text];
Run Code Online (Sandbox Code Playgroud)

结果如下:

In[92]:= Short[myData,5]
Out[92]//Short= 
tableContainer[{{Country / Region},{Unemployment rate (%)},{Source / date of information}},
{{Afghanistan},{35.0},{2008,{3}}},{{Albania},{13.49},{2010 (Q4),{4}}},
{{Algeria},{10.0},{2010 (September),{5}}},<<188>>,{{West Bank},{17.2},{2010,{43}}},
{{Yemen},{35.0},{2009 (June),{128}}},{{Zambia},{16.0},{2005,{129}}},{{Zimbabwe},{97.0},{2009}}]
Run Code Online (Sandbox Code Playgroud)

我喜欢这种方法(Import->XMLObject与之相反),因为我将网页转换为Mathematica表达式,语法最少(与XML对象不同),通常很容易建立一组替换规则来实现在每个给定的案例中进行正确的后处理.最后的免责声明是我的解析器不健壮并且确实包含许多错误,因此请注意.


Sza*_*lcs 6

不是直接回答如何导入HTML(其他人已经很好地解释),但从HTML表中获取数据正是我最初制作表格粘贴调色板的原因.

如果您的目标是获取数据,那么这可能比尝试解析页面更容易,更快捷.

使用调色板的说明

  1. 评估创建调色板的表达式,转到Palettes - > Install Palette ...并将其永久保存以供以后使用(如果您愿意).

  2. 在网页上选择表格的一部分.如果您正在使用Firefox,请按住CTRL以选择表格的任何矩形部分(非常有用!)复制它.

  3. 如果您使用的是Firefox或Chrome,请按TSV调色板上的按钮将数据粘贴到当前插入点的笔记本中.我不确定其他浏览器在复制时是否也会使用标签分隔项目.

结果将如下所示:

{{"Afghanistan", 35.`, "2008[3]"}, {"Albania", 13.49`, 
  "2010 (Q4)[4]"}, {"Algeria", 10.`, 
  "2010 (September)[5]"}, {"American Samoa (United States)", 23.8`, 
  "2010[3]"}, {"Andorra", 2.9`, 2009}}
Run Code Online (Sandbox Code Playgroud)

如您所见,需要进行一些后处理才能将年份转换为适当的格式(字符串或整数?)


这是旧的调色板代码.我意识到它需要清理,但它按原样工作,我还没有时间修复它.在下面的评论中报告任何问题.

CreatePalette@Column@{Button["TSV",
    Module[{data, strip},
     data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]];
     strip[s_String] := 
      StringReplace[s, RegularExpression["^\\s*(.*?)\\s*$"] -> "$1"];
     strip[e_] := e;
     If[Head[data] === String,
      NotebookWrite[InputNotebook[],
       ToBoxes@Map[strip, ImportString[data, "TSV"], {2}]]
      ]
     ]
    ],
   Button["CSV",
    Module[{data, strip},
     data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]];
     strip[s_String] := 
      StringReplace[s, RegularExpression["^\\s*(.*?)\\s*$"] -> "$1"];
     strip[e_] := e;
     If[Head[data] === String,
      NotebookWrite[InputNotebook[],
       ToBoxes@Map[strip, ImportString[data, "CSV"], {2}]]
      ]
     ]
    ],
   Button["Table",
    Module[{data},
     data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]];
     If[Head[data] === String,
      NotebookWrite[InputNotebook[],
       ToBoxes@ImportString[data, "Table"]]
      ]
     ]
    ]}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ure 5

Import[
  "http://en.wikipedia.org/wiki/Unemployment_by_country",
  "Data"]
Run Code Online (Sandbox Code Playgroud)

当然,结果经常需要进一步处理.你想如何形象化它?

您可以Import使用找到所有类型

Import[
  "http://en.wikipedia.org/wiki/Unemployment_by_country",
  "Elements"]
Run Code Online (Sandbox Code Playgroud)