Извлечение информации из HTML с помощью Mathematica - PullRequest
18 голосов
/ 11 января 2012

Существует ли простой способ извлечения данных из определенных таблиц HTML с помощью Mathematica? Import кажется довольно мощным, и Mathematica, кажется, способна хорошо обрабатывать такие форматы, как XML.

Вот пример: http://en.wikipedia.org/wiki/Unemployment_by_country

Ответы [ 6 ]

13 голосов
/ 11 января 2012

Для общих примеров этого есть следующие инструкции:

Для этого конкретного примера просто импортируйте его

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. Необходима дальнейшая очистка, иначе произойдет много промахов. Очистка включает в себя удаление ссылки на «суверенную страну» в скобках. например "Гуам (США)" -> "Гаум".

tmp2 = Flatten[
  If[StringMatchQ[#, __ ~~ "(" ~~ __], 
     StringCases[#, 
      z__ ~~ Shortest["(" ~~ __ ~~ ")" ~~ EndOfString] :> 
       StringTrim@z], 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, а также изменять размер изображений, если необходимо.

6 голосов
/ 11 января 2012

Не прямой ответ на вопрос о том, как импортировать HTML (что хорошо объяснили другие), но получение данных из таблиц HTML - это точно , почему я изначально создал палитру вставки таблицы .

Если ваша цель - просто получить данные, вероятно, это будет проще и быстрее, чем пытаться разобрать страницу.

Инструкции по использованию палитры

  1. Оцените выражение, которое создает палитру, перейдите в Палитры -> Установить палитру ... и сохраните его навсегда для дальнейшего использования (если хотите).

  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}}

Как видите, некоторая постобработка необходима для преобразования лет в правильный формат (строка или целое число?)


Это старый код палитры. Я понимаю, что он нуждается в очистке, но он работает, как есть, и у меня еще не было времени, чтобы исправить это. Сообщите о любых проблемах в комментариях ниже.

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"]]
      ]
     ]
    ]}
6 голосов
/ 11 января 2012

Хотя использование 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[]}];

Тогда вы получите, я думаю, довольно полные данные по этому коду:

text = Import["http://en.wikipedia.org/wiki/Unemployment_by_country", "Text"];
myData = First@findAndParseTables[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), часто очень легко установить набор правил замены, который выполняет правильную постобработку в каждом конкретном случае.Последний отказ от ответственности заключается в том, что мой синтаксический анализатор не является надежным и содержит определенное количество ошибок, поэтому будьте осторожны.

5 голосов
/ 11 января 2012
Import[
  "http://en.wikipedia.org/wiki/Unemployment_by_country",
  "Data"]

Конечно, результат часто нуждается в дальнейшей обработке. Как вы хотите это визуализировать?

Вы можете найти все Import типы, используя

Import[
  "http://en.wikipedia.org/wiki/Unemployment_by_country",
  "Elements"]
4 голосов
/ 11 января 2012

Если вы хотите пойти по пути Import [..., "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

3 голосов
/ 11 января 2012

Для определенных значений «легко», да.См. Здесь: HTML Импорт документации для Mathematica 8.

Вы можете импортировать из таблиц, используя параметр формата "Data", например, Import["file.hml", "Data"].Это начало, но ваша ссылка представляет собой целое дерево DOM-таблиц, div и других вещей.Это задокументировано, но тонко, и вам придется экспериментировать.Однако он работает с URL.

Этот на самом деле работает .Немного почистив, вы можете использовать данные здесь:

Import["http://en.wikipedia.org/wiki/Unemployment_by_country", "Data"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...