В конце прошлой недели, возвращаясь домой в метро, я получил электронное письмо от одной из компаний, с которыми я беседовал. Вызов кода! Возбуждение! Он попросил меня не тратить на это больше нескольких часов. Легко, подумал я. Я начну сразу же по возвращении домой и удивлю их своим творчеством и драйвом.
Задача заключалась в том, чтобы я написал поисковый робот. Учитывая домен, скажем, «https://www.medium.com/@mikeappell», сканер должен найти каждый статический элемент и ссылку на этой странице (например, все ссылки, изображения, скрипты и т. д.) и создать карту сайта. Кроме того, для ссылок, которые находятся в этом домене (например, ссылка на другой блог medium.com), перейдите по этой ссылке и продолжите процесс там. В конце концов, вы возвращаете карту сайта, состоящую из всех статических элементов и ссылок, которые можно найти на этом первом сайте и в этом домене.
Сразу подумал: «Это работа на рекурсию!» Еще в метро я делал заметки на телефоне, как к этому подступиться, гуглил методы Нокогири, чтобы увидеть, не существует ли уже какой-нибудь рекурсивный метод (был). Наконец я добрался до дома, принял душ, поцеловал жену, и нырнул.
…ооооооо мальчик.
Во-первых, я понятия не имел, насколько глубоким будет уровень ссылок на вашем обычном сайте. Я достиг глубины стека 350 или около того, прежде чем начал получать ошибки переполнения стека, и все пошло наперекосяк. Я думал о хвостовой рекурсии, но не мог придумать подходящего способа структурировать сигнатуру метода. Итак, в страну итераций!
Я корпел над этой проблемой до 2:30 утра. Я никогда в жизни не сталкивался с таким количеством бесконечных циклов. Отладка этого зверя была одной из самых сложных вещей, которые мне приходилось делать: найти, где ваша логика дает сбой и цикл начинает возвращаться к уже пройденным страницам, было очень и очень сложно. Но я дошел до того, что был счастлив, отправил им ссылку на мой репозиторий на Github, продолжал работать над Readme до 3, а затем лег в постель, прежде чем потерять сознание.
Оглядываясь назад, это была забавная проблема, но я наивно полагал, что ответом будет простое рекурсивное решение. Конечно, есть способы реализовать это рекурсивно, но у моего подхода не было шансов. Однако я многому научился; по крайней мере, глубина перелинковки даже, казалось бы, простых веб-сайтов повергла меня в благоговейный трепет. Сайт WordPress друга достиг глубины 350, прежде чем стек переполнился. Я никогда не ожидал этого.
Кому интересно, репозиторий Github для моего кода можно найти здесь:
Мое рекурсивное решение можно найти в более ранних коммитах, хотя на тот момент все еще присутствовал значительный объем отладочного кода.
Кроме того, Readme содержит больше информации, чем пост здесь. Это было в основном ради того, чтобы написать что-нибудь об одной из самых интересных проблем, с которыми я столкнулся в последнее время.