1

Мне понадобилось распарсить таблицу на этой странице из кода на C#. Google подсказал мне откуда начать:

Распарсить HTML в .NET и выжить: анализ и сравнение библиотек

Как распарсить HTML в .NET?

Мой вывод: AngleSharp, так как:

  1. Поддерживается и развивается
  2. "...Количество различных плюшек, облегчающих работу просто поражает воображение, к примеру IHtmlTableElement..."

Ожидаю что выбранная библиотека поможет решить 2 задачи:

  1. извлечь и DOM страницы HTML-код таблицы;
  2. "облегчающим работу способом" в 1-2 команды преобразовать HTML в таблицу - некую форму, к которой из C# можно обращаться по строкам и столбцам.

Ищу как решить первую задачу. На главной странице проекта в GitHub в Simple demo сразу нахожу строку document.QuerySelectorAll(cellSelector); Этот метод выбирает все заданные элементы, а у меня только один. Разгадка близко. Следует изучить методы того класса, экземпляром которого является document и, среди них, ну точно будет искомый. А имя класса мне подскажет VisualStudio.

С главной страницы - очень удобно - сразу перехожу по ссылке Documentation. Requirements, Getting AngleSharp over NuGet, First steps, The DOM (отличная иллюстрация в тексте), Beyond the DOM (ага, снова var elements = document.QuerySelectorAll("li").Attr("test", "test");. Хороший текст, завершается жизнеутверждающим to be continued.

Хорошо, далее иду в Wiki. Вот они - все ответы! Documentation, API, Interfaces, Examples и ещё много ссылок но мне уже некогда. Да и не хочется. Хочется распарсить табличку.

Проверяю Documentation. Ну да, здесь уже был. API - открывается главная. Interfaces - открывается главная. Examples - открывается главная.

Пол-часа беспорядочных поисков. Ага, вот же в Documentation справа "Pages" - и с него ссылки ведут куда обещано.

Ещё раз по списку. API - просто текст, не вчитываюсь. Interfaces - просто текст, не вчитываюсь. Examples - есть код. 7 примеров. Документации нет. Ищу поиском "Query". Нахожу старого знакомого QuerySelectorAll и yahoo! var emphasize = document.QuerySelector("em"); Однако, закрадываются сомнения - Query это запрос, а запрос это что-то вроде List<IEnumerable>, а мне нужен 1 элемент с уникальным ID.

Очень хочу доки, в идеале - как на MSDN. Ну или примеры кода - мне всего-то несколько строк нужно приспособить. Без претензий к использованию памяти и производительности.

Ok, Google: "anglesharp samples", находится новая ссылка AngleSharp.Samples. Отличные картинки! На на картинках есть ссылка: http://anglesharp.github.io - тоже не то. Ладно, сверху дерево папок и файлы. AngleSharp.Samples.App не то, AngleSharp.Samples.Demos/Snippets/. Судя по названию, SingleElements.cs даст мне если не ответы на все вопросы, то пример каноничного кода. Увы, var emphasize = document.QuerySelector("em");

Ok Google, "anglesharp Get element by id": первые 4 ссылки подсвечены фиолетовым, я там уже был...

Вопрос: каков, в общих чертах, должен был быть ход рассуждений и действий, способный привести к искомому решению? (и ни в коем случае не давайте ссылку на доки)).

(Изучить все файлы проекта на GitHub это решение, признаю).

  • Если не секрет, который блок вы по Id пытаетесь достать? Мне просто чтобы понять, как по вашему пути размышлению попробовать найти решение. – Monk Feb 20 '16 at 17:03
  • id="optionQuotesProductTable1" - это самая большая таблица на странице. – Андрей Вдовенко Feb 20 '16 at 20:49

1 Answers1

2

Конечно простите, но такой огромный поток мыслей - скорей всего является признаком прокрастинации. Вы слишком всё усложняете, буквально на пустом месте. Не надо так много думать - надо было просто сесть и написать код.

Загрузив документ, для разбора таблиц с той страницы, достаточно буквально выполнить по одной строчке:

var underlier = document.QuerySelector("#optionQuotesUnderlierTable1") as IHtmlTableElement;
var products = document.QuerySelector("#optionQuotesProductTable1") as IHtmlTableElement;

А потом тупо в цикле перебираете их Rows(строки), и у каждого из них вытаскиваете нужные значения из Cells(ячейки).

При этом, во время написания этого кода я не заглядывал ни в Google, ни в какие-то сомнительные статьи на хабре, или "самсебеответы" здесь. Так же я никогда не смотрел примеры использования этой библиотеки.

Почему? Всё просто - у AngleSharp очень интуитивный, самодокументированный код. Кому этого недостаточно - автор снабдил весь код XML-комментариями. Можете просто смотреть подсказки в студии, либо если так хочется читать документацию в MSDN-стиле - натравите на него тот же Sandcastle. А ещё весь код покрыт тестами - это отличный, постоянно обновляемый источник примеров использования тех или иных классов/интерфейсов.


Однако, если если хоть немного посмотреть на указанную вами страницу, то во первых, окажется что использовать AngleSharp там не нужно - все данные они выдают и в виде JSON, общаясь из JavaScript-кода с сервером посредством AJAX:

http://www.cmegroup.com/CmeWS/mvc/Quotes/Option/190/G/J6/ATM?optionProductId=190&strikeRange=ATM&pageSize=500

Соответственно можно просто воспользоватся RestSharp, или каким-нибудь веб-клиентом с связке с JSON.NET, например.

Ну а во вторых, у них есть полноценное API на базе FIXML, которое использовать даже проще:
http://www.cmegroup.com/confluence/display/EPICSANDBOX/CME+Cleared+Trades+API

Sergey Rufanov
  • 8,500
  • 25
  • 37
  • Очень благодарен Вам за ответ. Я получил сверх того что хотел. Из уважения к потраченному Вами времени, я перечислю сделанные мной выводы. – Андрей Вдовенко Feb 20 '16 at 21:15
  • (1) Документация в искомом виде отсутствует (а не я её плохо искал). – Андрей Вдовенко Feb 20 '16 at 21:15
  • (2) Ситуация не являетя исключением для подобных библиотек - а, скорее, нормой – Андрей Вдовенко Feb 20 '16 at 21:15
  • (3) Подход "просто писать код" глядя на подсказки VisualStudio не является прокрастинацией по отношению к изучению сторонних библиотек – Андрей Вдовенко Feb 20 '16 at 21:15
  • (4) Я открыл для себя unit-тесты - крутейшая идея (смейтесь над чайником) – Андрей Вдовенко Feb 20 '16 at 21:16
  • (5) Узнал про Sandcastle - крутая штука, но теперь я Свободен и для этой задачи он врядли понадобится – Андрей Вдовенко Feb 20 '16 at 21:16
  • (6) CME что-то даёт бесплатно (честно говоря, сомневаюсь, буду выяснять). У третьих лиц котировки продаются по $5 за 1 месяц по 1 товару – Андрей Вдовенко Feb 20 '16 at 21:17
  • (7) Перечисленные в конце статьи альтернативные способы получения котировок открыли передо мной пропасть незнания, но и перекинули через неё мостик - чуть позже обязательно разберусь. – Андрей Вдовенко Feb 20 '16 at 21:17
  • (8) А пока сделаю быстро но как смогу: с помощью WatIn, открою страничку, подожду пока отработают скрипты и буду парсить табличку указанным методом. – Андрей Вдовенко Feb 20 '16 at 21:17
  • Примите от меня огромную благодарность. – Андрей Вдовенко Feb 20 '16 at 21:17
  • Одна мелочь не даёт покоя: не заглядывая в google можно узнать о QuerySelector и его перегрузках из подсказки. А как можно догадаться про as IHtmlTableElement? – Андрей Вдовенко Feb 20 '16 at 21:20
  • @АндрейВдовенко, просто такое изложение мыслей кажется для меня скорей литературно-писательским, а не программистким. В первый раз, о IHtmlTableElement можно узнать просто запустив код в отладчике, да посмотрев тип значения возвращаемого QuerySelector-ом. В последующие - просто понимаешь, что этот метод всегда возвращает объект у которого есть интерфейс IHtml???Element, да просто смотришь на название HTML-тега, информацию из которого пытаешься извлечь. – Sergey Rufanov Feb 21 '16 at 05:02
  • Благодарю, всё ясно. – Андрей Вдовенко Feb 21 '16 at 09:42