CoderCastrov logo
CoderCastrov
Математика

Mathematica и Джефф Безос

Mathematica и Джефф Безос
просмотров
3 мин чтение
#Математика
Table Of Content

    В этом уроке мы узнаем, как использовать возможности извлечения информации из веб-страниц в Mathematica для загрузки всех писем акционерам Джеффа Безоса.

    Я читал книгу "Working Backwards", в которой часто упоминается цитата из письма акционерам Джеффа Безоса, и я задумался... "почему бы мне не прочитать все его письма и посмотреть, что я могу узнать?" Итак, как любой хороший решатель проблем, я решил найти его письма акционерам и, о чудо, я нашел их.

    Затем я услышал, как Джордж сказал мне в голове: "Не хочешь сделать это интереснее?" Почему бы и нет? Вечер еще молод. Итак, я открыл Mathematica, нашел страницу, на которой находятся все письма акционерам, и приступил к работе.

    Что вам понадобится

    Задача, которую нужно решить: как загрузить все письма акционерам в папку на моем компьютере от самого старого до самого нового?

    Я провел некоторое поверхностное исследование страницы и заметил, что каждая ссылка является тегом a с классами .module_link .module_link-shareholders. Поэтому, естественно, следующий вопрос будет: "как можно извлечь эти ссылки и затем загрузить их программно?"

    Вступает Mathematica.

    Mathematica позволяет создавать веб-сессию, в которой вы можете программно управлять браузером. Это особенно полезно, когда вы парсите веб-страницы, которые генерируют контент с помощью JavaScript и т.д. Итак, мы хотим:

    Запуск браузера в Mathematica

    url = "[https://ir.aboutamazon.com/annual-reports-proxies-and-shareholder-](https://ir.aboutamazon.com/annual-reports-proxies-and-shareholder-\)letters/default.aspx" (-- (1) --)session = [StartWebSession](https://reference.wolfram.com/language/ref/StartWebSession.html?q=StartWebSession)["Firefox"] (-- (2) --)[WebExecute](https://reference.wolfram.com/language/ref/WebExecute.html?q=WebExecute)[session, {"OpenPage" -> url}] (-- (3) --)

    Если мы читаем код с низу вверх, то мы просим Mathematica запустить веб-браузер (3), используя Firefox (2) и загрузить его с URL-адресом (1).

    Извлечение тегов из открытой веб-сессии HTML-страницы

    allAs = [WebExecute](https://reference.wolfram.com/language/ref/WebExecute.html?q=WebExecute)[session, "LocateElements" -> "CSSSelector" -> ".module_link.module_link-shareholders"]

    [WebExecute](https://reference.wolfram.com/language/ref/WebExecute.html?q=WebExecute) позволяет вам находить элементы на странице, которые соответствуют заданному шаблону. Существует множество способов извлечения элементов из страницы, например, с использованием тега HTML или XPath и т.д. Для нас важно использовать CSSSelector. Это позволяет нам находить элементы, у которых тег CSS имеет определенный класс или идентификатор и т.д. В нашем случае мы хотим найти все теги a, которые имеют классы .module_link и .module_link-shareholders. Приведенный выше код создаст список [WebElementObject](https://reference.wolfram.com/language/ref/WebElementObject.html?q=WebElementObject), способ представления Mathematica некоторого элемента HTML.

    Извлечение атрибутов из объекта WebElementObject

    Теперь, из этих элементов мы хотим извлечь ссылки, чтобы загрузить их. Документация по Mathematica не ясна в этом вопросе. Однако Мурта (на Mathematica Stackexchange) написал замечательный код, который помогает нам.

    getAttribute[element_WebElementObject, attribute_String] := 
     getAttribute[$CurrentWebSession, element, attribute]getAttribute[session_WebSessionObject, element_WebElementObject, 
      attribute_String] := 
     With[{sessionInfo = session /@ {"SessionID", "Browser", "URL"}}, 
      WebUnit`Private`attribute[sessionInfo, element["ElementId"], 
       attribute]]

    Теперь мы можем использовать getAttribute для получения href, и мы почти готовы.

    allLinks = Reverse[getAttribute[#, "href"] & /@ allAs];

    Мы переворачиваем список, потому что, если вы обратите внимание на ссылки на странице, то они идут в порядке убывания, и мы хотим, чтобы они были в порядке возрастания.

    Загрузка файлов в папку

    Прежде чем мы приступим к загрузке писем, нам нужно немного подготовиться. Мы хотим загрузить письма так, чтобы имя каждого письма соответствовало году его написания. Другими словами, мы хотим что-то вроде "1997-Shareholder Letter" и так далее до 2020 года.

    namesAndLinks = 
     Table[{StringJoin[ToString[n], "-Letter to Shareholders.pdf"], 
       allLinks[[n - 1996]]}, {n, 1997, 2020}]

    У нас есть ссылки, а нам нужны соответствующие имена. Мы можем перебрать каждую ссылку и связать ее с именем, например, "1998-Letter to Shareholders.pdf", и все готово.

    Мы можем использовать [URLDownloadSubmit](https://reference.wolfram.com/language/ref/URLDownloadSubmit.html?q=URLDownloadSubmit) для сохранения файла на нашем компьютере по заданной ссылке. Он имеет три параметра: ссылка, имя файла, функция обработчика (что мы хотим сделать во время загрузки или после ее завершения и т.д.). Вы можете подумать: как я могу изменить место загрузки писем? Легко. Мы можем использовать [SetDirectory](https://reference.wolfram.com/language/ref/SetDirectory.html?q=SetDirectory), чтобы установить папку загрузки.

    URLDownloadSubmit[#[[2]], #[[1]], 
       HandlerFunctions -> <|"TaskFinished" -> Print|>] & /@ namesAndLinks

    И с этим небольшим фрагментом мы загрузим все письма акционерам Безоса в выбранную нами папку в порядке возрастания. 🎉