Инновационная программа веб-скрапинга для создания персонализированных рекомендаций по подержанным автомобилям

Когда я взял несколько выходных в колледже на День Благодарения в 2022 году, у меня наконец появилось столь необходимое свободное время. Хотя большую часть времени я провел со своей семьей, я также хотел приступить к личному проекту, в котором использовались бы навыки, приобретенные в этом семестре. В преддверии стажировки в компании Ericsson в Далласе, штат Техас, мне нужно было купить свою первую машину, но я мало знал о рынке подержанных автомобилей. Поток запутанных онлайн-ресурсов заставил меня чувствовать себя ошеломленным, поэтому я решил создать программу для проведения исследований за меня.

Так родился Каспер. Он просматривает онлайн-магазины подержанных автомобилей, такие как AutoTrader, CarsDirect, CarGuru, Carvana, Lowbook и KSL, в поисках данных о продажах подержанных автомобилей, используя пакет Python Selenium. Хотя в настоящее время Casper ищет автомобили только в районе Прово, штат Юта, он оценивает каждое транспортное средство для создания отчета в формате CSV о текущем рынке и регистрирует изменения рынка с момента его создания в ноябре 2022 года.

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

Название Casper является отсылкой к испанскому слову «raspar», что означает «соскабливать». Кроме того, он отдает дань уважения «Дружелюбному призраку Касперу», так как когда программа работает, кажется, что призрак управляет вашим компьютером!

Веб-скраппинг

Моей основной целью, когда я начал этот проект, было развитие моих навыков парсинга веб-страниц. Веб-скрапинг — это универсальный термин, который относится к извлечению значимых данных с веб-сайтов. Следуя набору запрограммированных инструкций, программа веб-скрапинга может идентифицировать и извлекать данные и сохранять их в базе данных или экспортировать в электронную таблицу. Я решил собрать Casper, используя пакет тестирования и автоматизации Selenium, чтобы провести «исследование» за меня.

Поскольку в то время я проживал в Прово, штат Юта, я сосредоточился на дилерских центрах с самым широким присутствием в этом регионе. Хотя Casper можно перенастроить для поиска других почтовых индексов и более крупных областей, программа не может работать в фоновом режиме и легко замедляется из-за долгой загрузки страниц. Я также счел наиболее полезным ограничить критерии поиска. К счастью, Casper позволяет пользователям вводить конкретные параметры поиска, включая диапазоны цен, диапазоны пробега, годы производства, город продажи и радиус, а также только новые или подержанные автомобили. С помощью этого ввода Casper просматривает популярные платформы подержанных автомобилей и извлекает из результатов поиска соответствующую информацию, такую ​​как год выпуска, марка, модель, цена, изображение и ссылка на листинг.

Программа имеет объектно-ориентированную структуру кода. Я создаю экземпляр объекта для каждого веб-сайта в основной функции. Поскольку каждый веб-сайт уникален и требует нескольких отдельных шагов, имело смысл создавать для каждого отдельный объект класса, а не абстрагировать их в один объект. Конструктор открывает соответствующий веб-сайт через Selenium и настраивает страницу, добавляя необходимые пользовательские фильтры, не включенные в URL-адрес. Наконец, конструктор вызывает каждый из методов поиска, например метод, описанный ниже.

Эта функция находит все цены, видимые на текущей странице. В этом примере я ищу по xpath, что означает, что Casper будет искать структуру HTML-кода, пока не найдет блок, соответствующий цене, используя метод find_elements объекта драйвера Selenium. Строковая переменная priceClass указывает Casper искать элемент «div» с атрибутом «data-qa», который имеет значение, равное «price». Цикл for внизу затем анализирует соответствующий список, чтобы в конечном итоге строковые объекты можно было привести к объектам int.

def findPrices(self):
    """
    Find the prices for each car
    :param self
    :return: prices (list): list of price strings
    """
    # initialize a list of prices to return
    prices = []

    # define the X-Path to search the HTML code
    priceClass = "//div[@data-qa='price']"

    # get a list of price elements and save the parsed text content
    priceElems = self.driver.find_elements(By.XPATH, priceClass)

    # add the text from the elements to the list
    for elem in priceElems:
        prices.append(elem.text.replace(",", "").replace("$", "").split()[0])

    # return the list of prices
    return prices

После того, как Casper извлекает данные из результатов поиска, он создает список объектов Car, сопоставляя каждый автомобиль с соответствующими параметрами. Каждый объект Car — это, по сути, словарь, который также вычисляет общую оценку автомобиля и обнаруживает любые ошибки парсинга. После создания всех объектов Car Casper добавляет очищенные результаты в CSV-файл, соответствующий текущему веб-сайту.

Поскольку большинство поисковых запросов дают несколько страниц только с 20–50 продажами на каждой, Casper переходит к следующей странице после очистки первой страницы, сбрасывает фильтры и продолжает процесс, пока не найдет все результаты. Полный процесс занимает около 30 минут, чтобы собрать в среднем 500 объявлений со всех шести веб-сайтов.

Сжатие изображений

Сбор до 500 изображений каждый день — важная задача, и она может быстро занять доступную память компьютера. Чтобы решить эту проблему, мне нужно было сжать изображения, чтобы они занимали меньше места и становились более управляемыми. Хотя такие пакеты, как OpenCV, предоставляют встроенные методы сжатия изображений, я решил использовать метод линейной алгебры, который я изучил на одном из моих классов ACME, чтобы создать собственный алгоритм для эффективного сжатия изображений. Вы можете найти подробную информацию об алгоритме в другом моем сообщении в блоге Раскрытие секретов сжатия изображений с помощью векторов.

По сути, метод под названием Singular Value Decomposition позволяет разбить изображение на составные части, определить наиболее важные и удалить наименее важные части вместе с данными, которые потребовались для их хранения. Когда вы рекомбинируете эти компоненты, результирующее изображение выглядит похожим, если не неразличимым для человеческого глаза, но требует значительно меньше места для хранения.

Алгоритм оценки

Функция подсчета очков, которую я написал, довольно проста. С большим количеством данных, таких как фирменное и чистое название, состояние, цвет и рейтинги, алгоритм был бы намного эффективнее, но для того, с чем мне приходится работать, он работает хорошо. У функции есть восемь входных данных: пробег автомобиля, цена, год выпуска, марка и веса для каждого из этих четырех параметров.

Веса позволяют пользователю сообщить Касперу, насколько важен для него каждый из этих параметров. Например, если бы пробег был в два раза важнее всего остального, веса были бы (2, 1, 1, 1) соответственно. Веса нормализованы, поэтому фактическое значение не имеет значения, имеет значение только относительное значение. Функция вычисляет сумму соотношений между записанными значениями и идеальными максимальными значениями, а затем умножает это значение на сто весовых коэффициентов. Это возвращает число от нуля до ста. Вот формула одного из таких расчетов на примере пробега.

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

Обнаружение повреждений

Хотя алгоритм подсчета очков работал последовательно, у него был существенный недостаток, препятствовавший его практичности. Автомобили, набравшие наибольшее количество очков, иногда получали хорошие оценки, потому что у них были видимые, а иногда и серьезные повреждения. В то время как ущерб очевиден для человеческого глаза, все, что могла увидеть функция подсчета очков, — это сильно сниженная цена предложения.

Чтобы решить эту проблему, я разработал модель машинного обучения, способную обнаруживать повреждения на изображениях автомобилей с точностью более 99%. Эта функция была на самом деле последним проектом для моего класса глубокого обучения, и он оказался более сложным, чем я изначально ожидал. Я считаю, что он также заслуживает отдельного поста, поэтому вы можете найти больше информации об этом в другом моем блоге «Обнаружение повреждений автомобиля с помощью передовой технологии глубокого обучения». Я потратил более тридцати часов, дополняя данные изображений транспортных средств общедоступными наборами данных о повреждениях автомобилей, чтобы обучить глубокую сверточную нейронную сеть U-Net классифицировать автомобили как поврежденные или неповрежденные.

Прогноз цен

Стремясь еще больше повысить точность подсчета баллов, я создал еще одну модель машинного обучения, которая предсказывает цену автомобиля на основе его характеристик. Используя этот подход в качестве фактора в моей оценочной функции, я мог оценить, стоит ли рассматривать листинг, сравнив его цену предложения с прогнозируемой ценой моей модели.

Поскольку мне нужно было больше данных о каждой машине, чтобы построить более точную модель, я начал с более полного набора данных, который нашел в Интернете. Немного очистив данные и разработав функции, я обучил нейронную сеть, которая использует встраивание данных за более чем 2000 эпох для достижения удовлетворительной производительности. Хотя модель продемонстрировала впечатляющие результаты на загруженных данных, мне все еще нужно адаптировать ее к ограниченным данным, которые собирает Casper, прежде чем она станет практичной для этого проекта.

Будущая работа

Как вы, возможно, заметили из многочисленных шагов, которые я предпринял для улучшения функции подсчета очков, дальнейшие улучшения ее точности и полезности алгоритма подсчета автомобилей остаются наиболее важными следующими шагами. В то время как текущая версия обеспечивает полезную основу для покупателей, сбор большего количества данных о каждом автомобиле позволит получить еще более точную оценку и дать более полезные рекомендации. Однако задача сбора дополнительных данных усложняется онлайн-программой, которая обнаруживает ботов и препятствует попыткам Casper просмотреть более подробную информацию о листингах. Обход этого препятствия позволил бы мне получить более полные данные и улучшить функцию подсчета очков.

Помимо улучшения алгоритма оценки транспортных средств, расширение возможностей Casper за счет включения аналитики рынка было бы интересной и увлекательной задачей. Имея данные за несколько месяцев, Casper сможет определить тенденции на местном рынке подержанных автомобилей и предоставить покупателям еще более полезную информацию. Например, он может определить лучшее время года для покупки, как долго конкретные автомобили остаются на рынке и как тенденции местного рынка сравниваются с национальными.

Наконец, Casper потребует постоянных обновлений, чтобы адаптироваться к любым изменениям дизайна, которые происходят на постоянно меняющихся веб-сайтах. Это техническое обслуживание обеспечит бесперебойную работу Casper и предоставление пользователям точной и актуальной информации.

Надеюсь, вы узнали что-то новое из этого проекта, а также из алгоритмов и методов, которые я применил для решения задач и разработки функций, необходимых для параметров проекта. Если вы хотите просмотреть репозиторий кода, вы можете посетить мой GitHub здесь. Я был бы признателен за любой вклад или отзыв, который вы можете предложить!