使用Mathematica从HTML中提取信息
有没有简单的方法使用Mathematica从特定的HTML表格中提取数据? Import
似乎非常强大,Mathematica似乎能够很好地处理XML等格式。使用Mathematica从HTML中提取信息
下面是一个例子:http://en.wikipedia.org/wiki/Unemployment_by_country
对于这种普遍的例子还有这些密技:
对于这个具体的例子只是导入
tmp = Import["http://en.wikipedia.org/wiki/Unemployment_by_country", "Data"]
清洁起来是相当有这种进口直线前进。该表是3列,以便从剩下的东西提取出来:
tmp1 = Cases[tmp, {_, _?NumberQ, _}, \[Infinity]]
你大概会想删除的方括号引用(?):
tmp1[[All, 3]] = Flatten[If[StringQ[#],
StringCases[#, x__ ~~ Whitespace ~~ "[" ~~ __ :> x], #] & /@ tmp1[[All, 3]]]
Grid[tmp1, Frame -> All]
注意你也可以添加头回来,如果你想在你的表,你可能
Grid[Join[{{"Country/Region", "Unemployment rate (%)",
"Source/date of information"}}, tmp1], Frame -> All]
纯粹主义者可能会反对的最后一步,但是当你刮数据通常你只想把工作做好,并且每个现场是个案前景。因此,一些手动检查和灵活性可以让您获得最快的整体结果
编辑
,如果你想要的标志,你也可以从CountryData
得到它们。需要进一步清理,否则会发生很多错失。清理包括删除括号中对“主权国家”的提及。例如“关岛(美国)” - >“Gaum”。
tmp2 = Flatten[
If[StringMatchQ[#, __ ~~ "(" ~~ __],
StringCases[#,
z__ ~~ Shortest["(" ~~ __ ~~ ")" ~~ EndOfString] :>
[email protected]], StringTrim[#]] & /@ tmp1[[All, 1]]]
这仍然会产生一些CountryData
不能识别的输出。
flags = CountryData[#, "Flag"] & /@ tmp2;
Cases[flags, _CountryData]
6未命中出190.从输出删除那些未命中:
flags = If[Head[#] === CountryData, {""}, {#}] & /@ flags; (*much faster than rule replacement*)
tmp2 = Join[flags, tmp1, 2];
Grid[tmp2, Frame -> All]
注意这需要一段时间来呈现。
为使用Grid
选项需要,可以很明显的风格和Grid
也如果需要调整图像。
关于'(*比规则替换更快*) ',这比你的代码更快:'List/@ Replace [flags,_CountryData - >“”,1 ]'。 (+1,btw) – 2012-01-12 10:21:07
你是对的。我测试过'ReplaceAll',它很慢。 “替换”要快得多。 – 2012-01-12 11:51:18
Import[
"http://en.wikipedia.org/wiki/Unemployment_by_country",
"Data"]
当然,其结果将经常需要进一步的处理。你想如何想象它?
可以使用
Import[
"http://en.wikipedia.org/wiki/Unemployment_by_country",
"Elements"]
我会以某种方式想象它,但主要的是首先创建一个对应于表的矩阵, 。 – 2012-01-10 20:20:30
如果''Data''不起作用,那么我会尝试''XMLObject'',然后仔细使用'Cases'。尽管如此,这种方法很快就会变得麻烦。 – 2012-01-10 20:22:36
+1用于指出“导入[...,”元素“] [。](http://reference.wolfram.com/mathematica/ref/Import.html#405487078) – Simon 2012-01-11 09:56:19
对于 '易' 的某些价值发现所有Import
类型的,是的。请参阅:HTML Import documentation for Mathematica 8.
您可以使用"Data"
格式选项(例如, Import["file.hml", "Data"]
。这是一个开始,但你的链接是一个完整的DOM树的价值表,divs和其他东西。它有文件记载,但很薄弱,你必须试验。它确实可以与URL一起工作。
这个实际上工作。带着几分清洗,你可以在这里使用的数据:
Import["http://en.wikipedia.org/wiki/Unemployment_by_country", "Data"]
虽然使用Import
可能是一个更好,更稳健的方式,我发现,至少在这个特定的问题,我自己的HTML解析器(出版在this thread),工作良好,少量的后处理。如果你从那里的代码并执行它,使用此功能增强它:
Clear[findAndParseTables];
findAndParseTables[text_String] :=
Module[{parsed = [email protected][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[]}];
然后你得到,我想,一个非常完整的数据通过这个代码:
text = Import["http://en.wikipedia.org/wiki/Unemployment_by_country", "Text"];
myData = [email protected][text];
这里是如何结果看起来:
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}}]
我喜欢什么有关此方法(而不是说,Import->XMLObject
)是的,因为我转换网页为最小的语法Mathematica表达式(例如不同XML对象),通常很容易建立一套替换规则,在每种情况下都能进行正确的后处理。最后一个免责声明是我的解析器不健壮,确实包含许多错误,所以要警告。
您必须有足够的材料才能编写现在另一本Mathematica书。其实,我希望你能做到。 ;-) – 2012-01-11 11:27:30
@ ndroock1谢谢!我正在努力,但最近我有太多的直接工作要有足够的空闲时间来快速完成。在SO这里回答帖子是一回事,但写一本认真的书需要更多的时间,至少在核心完成之前。希望能尽快获得更多时间。顺便说一句,有一个新的Mathematica SE网站的建议:http://area51.stackexchange.com/proposals/37304/mathematica。如果你还没有这样做,请考虑支持它。 – 2012-01-11 11:48:03
@ ndroock1只需添加到以前的内容:该提案现在正在将它的(希望是最终的)步骤从提交阶段提交到测试版。以下是不够的,它不会自动转入提交。 – 2012-01-11 12:03:22
如果您想要导入[...,“XMLObject”]路线,下面概述了您可以执行的操作。
首先,让页面:
page = Import["http://en.wikipedia.org/wiki/Unemployment_by_country", "XMLObject"];
接下来,获得的利息表(在这种情况下,大表也正好是第一的七个表此页):
table = Cases[page, XMLElement["table", ___], \[Infinity]][[1]]
接下来,从table
得到row
,我挑选的第四行与对应阿尔及利亚:
行=例[表,的XMLElement [ “TR”,___],[Infi的无穷大]] [[4]]
接着,从该行中提取表的数据元素():
data = Cases[row, XMLElement["td", ___], \[Infinity]]
缺货那些元件的,可以挑例如国家标志缩略图,像这样:
image = Cases[data, XMLElement["img", {___, "src" -> src_, ___}, _] :> src, \[Infinity]]
最后导入图像的缩略图(它需要的 “http:” 前面加上出于某种原因):
Import["http:" <> image]
这是笔记本电脑是什么样子(缩略图,加上其它输入):
没有直接回答如何导入HTML(该人已很好地解释),但获得的数据来自HTML表格是恰恰是为什么我原来是我的table paste palette。
如果您的目标是获取数据,这可能比尝试解析页面更容易,更快速。使用调色板
-
指令计算创建调色板,去调色板的表达 - >安装面板...并永久保存以备后用(如果你愿意的话)。
在网页上选择一部分表格。如果您使用Firefox,请按住CTRL以选择表格的任何矩形部分(非常有用!)将其复制。
如果您使用的是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}}
正如你所看到的,需要一些后处理多年转换成合适的格式
(字符串或整数?)
这是旧的调色板代码。我意识到它需要清理,但它仍然可以正常工作,而且我还没有时间来修复它。在下面的评论中报告任何问题。
[email protected]@{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[],
[email protected][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[],
[email protected][strip, ImportString[data, "CSV"], {2}]]
]
]
],
Button["Table",
Module[{data},
data = NotebookGet[ClipboardNotebook[]][[1, 1, 1]];
If[Head[data] === String,
NotebookWrite[InputNotebook[],
[email protected][data, "Table"]]
]
]
]}
这工作完美无瑕。非常便利。 – 2012-01-11 19:44:55
这很好。我希望我能理解正则表达式。它似乎很神秘:) – 2012-01-11 21:35:25
@Mike它只是一个'StringTrim'。我为最初的Mathematica 6写了这个,里面没有'StringTrim'。 – Szabolcs 2012-01-11 22:29:47
IMO,如果您使用的是版本8,JSON是要走的路。在野外有大量的API(通常以您的方式抛出XML或JSON)。我不会建议杀死时间从Wiki中翻译失业数据。找到你感兴趣的主要来源,它可能会有一个API。如果您只想快速翻阅某些内容,也可以尝试在Excel中链接单元格,然后您可以导入到MMA中。 (如果你只是想玩得开心并学习,那么忽略所有这一切,在这种情况下,解析掉):D – telefunkenvf14 2012-01-11 01:34:25