Извлечение информации из HTML с помощью Mathematica
Есть ли простой способ извлечения данных из конкретных таблиц HTML с помощью Mathematica? Import
кажется довольно мощным, и Mathematica, похоже, способен обрабатывать форматы, такие как XML, довольно хорошо.
Вот пример: http://en.wikipedia.org/wiki/Unemployment_by_country
Ответы
Ответ 1
Для общих примеров этого есть следующие способы:
Для этого конкретного примера просто импортируйте его
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]
пуристы могут возражать против последнего шага, но когда вы очищаете данные, вы просто хотите выполнить задание, и каждый сайт - это случайная перспектива. Поэтому некоторые ручные проверки и гибкость дают вам самый быстрый общий результат.
Edit
если вам нужны флаги, вы также можете получить их из CountryData
. Некоторая дальнейшая очистка необходима, иначе будет много промахов. Очистка включает в себя удаление ссылки на "суверенную страну" в скобках. например "Гуам (Соединенные Штаты)" → "Гаум".
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]
Обратите внимание, что для рендеринга это занимает некоторое время.
![enter image description here]()
Вы можете, очевидно, пометить Grid
с помощью Grid
опций, а также изменить размер изображений, если это необходимо.
Ответ 2
Хотя использование Import
, вероятно, является лучшим и более надежным способом, я обнаружил, что, по крайней мере для этой конкретной проблемы, мой собственный HTML-парсер (опубликованный в этот поток), отлично работает с небольшим количеством последующей обработки. Если вы берете код и выполняете его, добавив его с помощью этой функции:
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), часто бывает очень легко установить набор правил замены, которые делают правильную пост-обработку в каждом конкретном случае. Окончательный отказ от ответственности заключается в том, что мой синтаксический анализатор не является надежным и наверняка содержит несколько ошибок, поэтому будьте предупреждены.
Ответ 3
Непосредственный ответ на вопрос о том, как импортировать HTML (что хорошо объяснили другие), но получение данных из таблиц HTML именно поэтому я изначально сделал таблицу пастообразная паста.
Если ваша цель - просто получить данные, это, вероятно, будет проще и быстрее, чем пытаться разобрать страницу.
Инструкции по использованию палитры
-
Оцените выражение, создающее палитру, перейдите в "Палитры" → "Установить палитру..." и сохраните ее навсегда для последующего использования (если хотите).
-
Выберите часть таблицы на веб-странице. Если вы работаете с 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"]]
]
]
]}
Ответ 4
Import[
"http://en.wikipedia.org/wiki/Unemployment_by_country",
"Data"]
Конечно, результат будет часто нуждаться в дальнейшей обработке. Как вы хотите визуализировать его?
Вы можете найти все типы Import
, используя
Import[
"http://en.wikipedia.org/wiki/Unemployment_by_country",
"Elements"]
Ответ 5
Если вы хотите перейти по маршруту Импорт [..., "XMLObject" ], вот схема того, что вы можете сделать.
Сначала зайдите на страницу:
page = Import["http://en.wikipedia.org/wiki/Unemployment_by_country", "XMLObject"];
Затем найдите интересующую таблицу (в этом случае большая таблица также является первой из семи таблиц на этой странице):
table = Cases[page, XMLElement["table", ___], \[Infinity]][[1]]
Затем, получив row
из table
, я выбрал четвертую строку, которая соответствует Алжиру:
row = Cases [table, XMLElement [ "tr", ___], [Infinity]] [[4]]
Затем извлеките элементы данных таблицы() из этой строки:
data = Cases[row, XMLElement["td", ___], \[Infinity]]
Из этих элементов вы можете выбрать, например, миниатюру флага страны, например:
image = Cases[data, XMLElement["img", {___, "src" -> src_, ___}, _] :> src, \[Infinity]]
Наконец, импортируйте миниатюру этого изображения (по какой-то причине она была добавлена "http:" ):
Import["http:" <> image]
Это выглядит как ноутбук (миниатюра, а также другие входы):
![Mathematica graphics]()
Ответ 6
При определенных значениях "легко" да. См. Здесь: Документация по документу HTML для Mathematica 8.
Вы можете импортировать из таблиц с помощью параметра формата "Data"
, например. Import["file.hml", "Data"]
. Это начало, но ваша ссылка - это целая таблица таблиц, разделов и других вещей DOM. Это задокументировано, но тонко, и вам придется экспериментировать. Однако он работает с URL-адресами.
Это действительно работает. С небольшим количеством очистки вы можете использовать данные здесь:
Import["http://en.wikipedia.org/wiki/Unemployment_by_country", "Data"]