Mathematica и Джефф Безос
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
И с этим небольшим фрагментом мы загрузим все письма акционерам Безоса в выбранную нами папку в порядке возрастания. 🎉