Ответы пользователя по тегу Парсинг
  • Как автоматически скачивать файл с сайта регулярно?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Чтобы это сделать вам нужно освоить selenium.
    С помощью него можно делать скрипты автоматизации имитирующие действия пользователя в браузере.
    Ответ написан
    Комментировать
  • Как создать свой сервис Аналитики\статистики?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    https://grafana.com/
    Есть и другие, но это по описанию подходит лучше всего.
    А данные надо хранить в БД, а не в экселе
    Ответ написан
    Комментировать
  • Как исправить AttributeError: 'NoneType' object has no attribute 'find_all'?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    1. Нужно приводить сообщение об ошибке полностью. Всё целиком что пишется в терминал. Там исчерпывающая информация о том, что конкретно и где пошло не так.
    2. Если вы не способны читать сообщения об ошибках, то вам надо учиться на более простых примерах. Сейчас же ваша проблема выглядит так, что вы совершенно не умея программировать и не зная основ пытаетесь с помощью данного ресурса решить свою какую-то задачу.
    3. У вас в коде только два места. где происходит вызов метода find_all. В котором конкретно ваша проблема указано в подробном сообщении об ошибке, которое вы не потрудились привести.
    4. 'NoneType' object has no attribute 'find_all' означает, что вы пытаетесь вызвать метод у объекта, у которого нет этого метода. Видно даже у какого объекта - у Null.
    5. Если вам этих намёков не достаточно, то вам следует взять учебник по питону и начинать учиться с простого. Или обратитесь к фрилансерам за помощью.
    Ответ написан
    Комментировать
  • Почему не парсятся ссылки на python?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Смотрите внимательно как устроен ваш парсер. Вам уже намекнули в соседнем ответе.
    Вы парсите статью так, будто бы её текст весь в одной строке (во второй по счету). А ссылки вы ищете в третьей строке, но из-за того, что статья многострочная там их нет.

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

    ВОт вы почему-то свято уверены, что lines[2][8:] - это перечень ссылок через запятую. Может быть даже в одном из примеров в какой-то момент когда-то так оно и было, но с тех пор вы уже поменяли, скорее всего, код или входной формат, но не учли это.
    Делайте больше отладочного вывода. Лучше не принтами, а с использованием модуля logging, тогда отладочный выхлоп можно включать и отключать при необходимости не трогая код.
    Каждый раз, когда вы меняете код, не важно для исправления старых ошибок, или для добавления новой функциональности, вы неизбежно вносите новые ошибки.
    Чтобы это контролировать пишут юнит-тесты. Но вам, похоже, еще рановато.
    Ещё, особенно в небольших скриптах, полезно убеждаться, что всё идёт как надо в промежуточных этапах. Для этого в питоне есть ключевое слово assert.
    Оно позволяет указать обязательное условие, которое должно соблюдаться в этом месте выполнения программы, и текст ошибки, с которой упадёт программа в этом месте, если условие не соблюдается.
    Конкретно здесь, можно было бы убедиться с помощью assert, что в третьей строке вы отрезали 8 символов и эти символы соответствуют префиксу "Images: ".
    Падение программы на этом месте даст вам понять, что вы где-то ошиблись и что-то пошло не так, как вы ожидали. Эти ассерты также помогут вам сразу обнаруживать изменение входного формата данных, за который, возможно, отвечает не ваш код.
    Ответ написан
    Комментировать
  • Как обойти блокировки сайтов?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Вы столкнулись с типичным конфликтом интересов. Видимо стиму не выгодна ваша деятельность и они хотят её осложнить для вас, сделать её для вас дороже.
    Это как борьба с читерством.
    Никто вам не скажет правил, по которым вас блокируют, иначе вы тут же начнёте их обходить. Более того, чтобы правила не обходили, их рандомизируют, динамически меняют, разносят во времени момент принятия решения о недобросовестности клиента и момент его блокировки, чтобы нельзя было по своим действиям и реакции системы блокирования понять и вычислить правила блокировки. Лаг между этими моментами всячески варьируют, рандомизируют, дают разное число попыток, чтобы осложнить подбор и вычисление граничных критериев системы защиты.

    Не факт, конечно, что там именно такая параноидальная и замороченная система, но такое определённо имеет смысл, если надо предотвратить долбёжку и не целевое использование АПИ.

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

    Ещё вы рандомизируете юзер-агент, но возможно имеет смысл притвориться браузером и не скакать по юзер-агентам так уж часто, тем более по рандомным.
    Сопоставить запросы между собой можно и при разных адресах, а выходные адреса тора, как вам уже сказали в комментарии к вопросу, немногочисленны и всем известны.
    Ответ написан
  • Бесплатный python хостинг?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Использование для своих корыстных не учебных целей сервисы вроде https://replit.com/ - это своего рода пробежка по граблям и нецелевое недобросовестное использование хорошего сервиса. Даже не буду вам рассказывать способы, которыми можно эксплуатировать уязвимости таких сервисов и преодолевать их ограничения. Считаю это неэтичным. Да и полно таких инструкций в сети, ищите сами, если хотите.

    Но я почитал ваши комментарии к другому ответу и вот что я вам скажу. Если ваш код работает на домашнем компе, а не работает на хостинге, это скорее всего проблема именно вашего кода и очень маловероятно, что это как-то связано с ограничениями хостинга.

    Часто код бывает не правильно написано в плане кроссплатформенности, использует какие-то глобально установленные библиотеки, которые вы забвли поставить на хочтинге, неправильно работает с кодировками или файловой системой.

    Для таких задач как ваша надо брать VDS. Подойдёт самая дешевая баксов за 5. А ещё у таких VDS есть бесплатный пробный период. Обычно это сутки, но я сталкивался и с недельными интервалами. Вот поищите https://poiskvps.ru/
    Там они не бесплантые, но есть тарифы с бесплатными пробными периодами. Однако, повторюсь, скорее всего не хостинг плохой, а ваш код косой.
    Ответ написан
    Комментировать
  • Как отправлять много запросов get (python) чтобы не забанили на сайте?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Вы даже не написали о каком сайте речь.
    Банить могут не за частоту, а по совокупности факторов.
    У такого бана всегда есть свои цели. К примеру, метрики показывают владельцам сайта, что существенную часть нагрузки создают вот такие автоматические запросы. Как именно владельцы сайта будут стараться отличить автоматические запросы от человеческих зависит от изобретательности разработчиков.
    Ещё одной причиной, почему владельцы сайта могут стремиться блокировать автоматические запросы - это нежелание делиться данными, публикуемыми на сайте с конкурентами или нахлебниками.

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

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

    В любом случае нужно стараться максимально затруднить вычисление причинно следственной связи между действиями бользователя\парсера и баном. Можно, к примеру, вести рейтинг клиентов и подключений, а когда этот рейтинг подозрительности достигнет некоторого порога, с некоторой вероятностью за рандомную единицу времени банить такого клиента. Если недобросовестному клиенту повезло и его не забанили сейчас, то забанят чуть позже, зато он не "расскажет" другим клиентам о критериях и не поможет им подстроиться под порог бана.

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

    Если защита на сайте сложнее, то и бороться с нею будет сложнее.

    Нет протого ответа на ваш вопрос, тем более такой наивно абстрактный.
    Ответ написан
    Комментировать
  • Как правильно подать GET запрос чтобы страница изменилась?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Смотрите. Вот у вас задача - получить отзывы так, чтобы новые были сверху.
    Вы дёргаете урл страницы с отзыывами и суёте в заголовки параметр с указанием сортировки. Но с чего вы вообще взяли, что АПИ принимает этот параметр через заголовки?

    Как следовало бы вам решать эту проблему. Метод годный для многих случаев.
    Нажимайте в хроме F12, выбирайте вкладку Networking и меняйте сортировку (мышкой на страничке). Смотрите, там появляется новый запрос, который страница делает через аякс не перезагружаясь полностью:
    https://yandex.ru/maps/api/business/fetchReviews?a...
    У вас запрос по конкретно этому урлу не выдаст данных, поскольку scrf-токен будет не актуальным и сессия не будет валидной. Чтобы получить токен и сессию вы можете сделать штатный гет запрос к странице. как вы делали в своём посте.
    Имея необходимые токены вы можете делать запросы с параметром ajax и не придётся парсить страницу выуживая данные, они будут сразу в json.
    Ответ написан
    2 комментария
  • Как посчитать количество суб-объектов в Python для каждого XML-объекта?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Вы можете сделать это за два прохода.
    На первом проходе просто собираете множество всех возможных уникальных тегов. Я бы просто записывал в словарь True по ключу, равному имени каждого попавшегося тега на первом проходе.
    В результате вы получите словарь уникальными именами в ключах, причем эти ключи будут в том порядке, в каком они встречались в XML (иногда это просто удобно, что они не в рандомном порядке).
    Имея общий набор имён вы можете воспользоваться стандартным способом записи в CSV в виде словарей.
    Останется лишь конвертировать каждый узел из вашего файла в словарь. Никаких сторонних библиотек не нужно.
    Ответ написан
    1 комментарий
  • Не могу передать строку в writerow, что не так?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Вот это кошмар...
    Нагромождение каких-то ненужных приседаний и реверансов. Склажывается ощущение. что код писался вообще без понимания что и как работает.
    Тут проще пересчитать строки, которые не требовалось бы исправить: ноль таких строк.
    Вы бы привели хоть пример что у вас там в property подается. А-то на кофейной гуще гадать приходится какая из сотни ошибок-таки окончательно стедала неработоспособным код.

    Вот здесь вообще какая-то ерунда:
    for i in range(j, len(property)):
        k = j
        write_to_csv(property[k])
        k += 1
      j = len(property)

    Ладно, с отступами беда. Но зачем эти бессмысленные присвоения? Зачем этот бессмысленный цикл, если вы в нем обрабатываете один и тот же элемент много раз?
    Прекращайте уже такое писать. Смысла нет. Не ваше.

    Похоже (разводы гущи так подсказывают за неимением других данных) вы не понимаете что передаёте в эту свою функцию. Ситуацию бы прояснила публикаия содержимого переменной roperty
    Ответ написан
    3 комментария
  • Получится ли открыть несколько wget?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Нет подвоха. Можно даже с помощью xargs такое сделать.
    Ответ написан
    Комментировать
  • Защита от скачивания видео на образовательных платформах?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Ок, Алиса, привет!

    1. самые разные защиты бывают. Самые неудобные - это самопальные плееры, для которых ешё не набралось критической массы желающих скачивать контент, чтобы сделать плагин к youtube-dl.
    2. Отсутствие ссылки на скачивание; доступность видео для просмотра только под авторизацией, что может помешать использовать youtube-dl.
    2. Не узнает скорее всего.

    Всегда есть возможность захвата видео с экрана. Пострадает качество, придётся потратить на захват время, равное длительности курса, но такой захват очень сложно предотвратить. В крайнем случае как в древности -- снимете экранку с монитора на телефон=).
    Ответ написан
    2 комментария
  • Как вычислить время, которое идёт матч?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Но это плохо работает и время считается немного не так.
    Подскажите, как лучше поступить.

    Так вы делайте немного по-другому и будет работать лучше.
    Ответ написан
    2 комментария
  • Как спарсить и скачать все картинки с сайта?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Посмотрите в сторону консольной утилиты wget. Ее вполне можно поставить и под виндой. Она (утилита) уже умеет скачивать сайт целиком вместе с картинами следуя по ссылкам со страницы на страницу.
    Прочитайте ее документацию.
    Там есть опция рекурсивной загрузки -r.
    Ответ написан
    Комментировать
  • Как парсить очень сложный текст?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    Если вы хотите что-то парсить, это значит, что этого "чего-то" очень-очень много. Тем более, если хотите применять ML. В этом случае нужна еще и обучающая выборка, где есть много-премного примеров входных данных в размеченном виде.
    К примеру на сайте службы доставки есть районы, где они работают

    Из вопроса не ясно сколько "грязных" данных есть. Неужели на одном единственном сайте службы доставки НАСТОЛЬКО много адресов в таким виде? Или таких сайтов миллион?
    Паресеры и ML превосходят возможности человеческой обработки только на больших, очень больших масштабах.

    Из вашего вопроса складывается впечатление, что вы спрашиваете как сделать некий парсер, который будет парсить ЛЮБЫЕ грязные данные произвольного вида и типа в любых количествах.
    Детализируйте свой вопрос, Показывайте больше примеров.

    Сильного ИИ ещё не существует (а когда появится, он будет не менее ленив, чем те, кому призван помогать).

    Для вас с вашим слишком общим вопросом есть только общие рекомендации.
    извлеките данные в текстовом виде;
    • просмотрите глазами: если писать парсер дольше, чем перелопатить вручную, а при пополнении в датасет может прийти совершенно нового вида мусор, то парсер не нужен, обрабатывайте руками;
    • настраивайте обработку датасета по ступенчатой схеме так, чтобы на каждой ступени происходили минимальные не калечащие изменения как можно большего объёма данных, а выхлоп передавался на следующую ступень без потери данных предыдущего шага;
    • просматривайте изменения, затронутые каждым шагом, если видите порчу данных, делайте дополнительные промежуточные шаги;
    • серией ступеней из простых замен по шаблону и рег-экспу делайте текст более структурированным: заменяйте разделители по паттернам, экранируйте или удаляйте содержимое скобок, заменяйте кавычки на однотипные, убирайте мусорные элементы, которые гарантированно не дадут сведений о полезных данных; раскрывайте аббревиатуры и сокращения, приводите синонимы к одному из вариантов...
    • на каком-то этапе ваш входной датасет должен превратиться из монолитного текста в CSV-поток с одной единицей данных на строку;
    • дальше так же ступенчато делайте чистку и дедупликацию потока, разделяйте записи на отдельные поля, выделяйте новые атрибуты.

    Постройте пайп-лайн так, чтобы изменения, внесённые каждым шагом можно было анализировать в виде диффа. Сделайте отдельный аналитический "вью", где будут видны только затронутые правкой ступени данные. Сразу видно будет косяки и калечащие изменения.
    Считайте статистику правок каждой ступенью, реагируйте на крайней случаи.
    Важно, что на каждом этапе энтропия датасета должна уменьшаться. Любая потеря данных вредна, поскольку заметить, скажем, что у вас "г." обозначает не только город, но и, к примеру, "гражданский" в большом количестве топонимов в конце обработки -- это фатально. Вы запутаетесь. Нужно выносить удаляемые данные в отдельные поля и оставлять возможность делать по ним анализ на более поздних этапах.
    В целом исходный датасет у вас всегда созранён и всегда можно быстро повторить шаги.
    Сохраняйте этапы написания парсера в системе контроля версий, делайте чаще коммиты с внятными описнаиями.
    И да хранит вас Кнут и Страуструп.
    Ответ написан
    Комментировать
  • Где найти годный парсер адресов?

    trapwalker
    @trapwalker
    Программист, энтузиаст
    У вас в примере очень чистые аккуратные адреса.
    Не очень понятно что вы имели в виду под "разложить по полочкам" и какие именно вам нужны полочки.
    Общий подход для переработки таких массивов слабо структурированных данных следующий.
    1. Процесс переработки должен быть поэтапный. Каждый этап должен вносить минимальные не калечащие изменения в как можно бОльшую часть датасета.
    2. Каждый этап должен быть прозрачным. Затронутые модификацией значения можно для удобства контроля (глазами) дедуплицировать и сортировать. Это позволит легко увидеть любые аномалии.
    3. Нужно вести подробную статистику изменений на каждом этапе. Все выбросы статистики должны проверяться глазами: слишком короткое минимальное слово или число слов, слишком длинные слова или наборы, слишком большие или малые числа...
    4. На каждом этапе нужно сохранять предыдущее состояние датасета или держать исходное и иметь удобный инструментарий для быстрого полного накатывания всех этапов на исходный датасет. Иногда этапы имеет смысл переставить местами, потому что обнаружилось незамеченное ранее калечащее изменение пару этапов назад.
    5. Серия мелких правок простыми операциями предпочтительнее сложных алгоритмов и регэкспов. Например в вашем случае гораздо лучше серией прсотых и понятных реплейсов заменить "ул." на "улица", "пл." на "площадь" и т.д.
      Чтобы не городить сложные регекспы имеет смысл сплитнуть строки по словам и заменять слова целиком, либо одним из шагов добавить в начало и конец строки пробелы. Это упростит регекспы и не даст наделать незаметных сразу косяков.
      Затронутые реплейсами строки можно отсортирвоать и дедуплицировать для просмотра глазами. Вдруг у вас есть много переулков Плава-Лагуны, которые принято тоже так сокращать.
    6. Если у вас есть справочник улиц, можно все записи в обработанном датасете, для которых нашлось однозначное соответствие улицы из справочника, пометить специальным флагом и больше не трогать в них улицы. Остаток можно снова подвергнуть сортировке и дедупликации (заодно можно частотность посчитать) и вычищать массово или точечно начиная с чамых частых случаев реплейсами, регекспами, и т.д.

    В вашем случае:
    1. Разделите адреса по запятой, сохраните в отдельные поля. лучше CSV, а не в БД. Проще. При обнаружении больше двух (в вашем случае) запятых сразу падайте, кричите, считайте число таких случаев, решайте вручную, если их не много, делайте отдельный фильтр с фиксом на отдельном этапе если много.
    2. Отсортируйте и дедуплицируйте (на секундочку) все три столбца по отдельности, просмотрите глазами получившиеся множества, поищите проблемы. Автоматизируйте этот шаг, он вам понадобится еще не раз.
    3. Обработайте датасет серией очевидных реплейсов, которые снизят разнообразие. Устранятся сокращения, множественные варианты одного и того же написания, различия в регистрах букв.
    4. Вытащите из ФИАС каталог улиц. Можно взять в формате КЛАДР, там попроще может оказаться и в отдельном файле. Разметьте очищаемый датасет ссылками на найденные в справочнике улицы. Просмотрите дедуплицированные и отсортированные (по алфавиту и по частотности) оставшиеся улицы. Поищите стандартные проблемы, которые можно пофиксить автоматически, внесите ручные правки для узких частных случаев (но программно реплейсами в отдельном этапе, чтобы можно было повторно обработать исходный датасет).


    Если у вас датасет весь примерно такой, как в примере, то я за пару тысяч рублей его вам почищу независимо от его размера. Почти независимо.=)
    Ответ написан
    2 комментария
  • Почему парсер всех внутренних ссылок сайта на Python не хочет парсить некоторые сайты?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    На в каждом теге "a" есть `href`.
    from urllib.parse import urlparse
    from bs4 import BeautifulSoup
    import requests
    import lxml
    DOMAIN = 'apexair.ru'
    HOST = 'http://' + DOMAIN
    FORBIDDEN_PREFIXES = ['#', 'tel:', 'mailto:']
    links = set()  # множество всех ссылок
    headers = {
            'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'}
    response = requests.get(HOST, headers=headers)
    # print(response.content)
    
    def add_all_links_recursive(url, maxdepth=1):
        # print('{:>5}'.format(len(links)), url[len(HOST):])
    
        # глубина рекурсии не более `maxdepth`
    
        # список ссылок, от которых в конце мы рекурсивно запустимся
        links_to_handle_recursive = []
        # получаем html код страницы
        request = requests.get(url, headers=headers)
        # парсим его с помощью BeautifulSoup
        soup = BeautifulSoup(request.content, 'lxml')
        # рассматриваем все теги <a>
    
        for tag_a in soup.find_all('a', href=lambda v: v is not None):
            link = tag_a['href']
    
            # если ссылка не начинается с одного из запрещённых префиксов
            if all(not link.startswith(prefix) for prefix in FORBIDDEN_PREFIXES):
                # проверяем, является ли ссылка относительной
                # например, `/oplata` --- это относительная ссылка
                # `http://101-rosa.ru/oplata` --- это абсолютная ссылка
                if link.startswith('/') and not link.startswith('//'):
                    # преобразуем относительную ссылку в абсолютную
                    link = HOST + link
                # проверяем, что ссылка ведёт на нужный домен
                # и что мы ещё не обрабатывали такую ссылку
                if urlparse(link).netloc == DOMAIN and link not in links:
                    links.add(link)
                    links_to_handle_recursive.append(link)
    
        if maxdepth > 0:
            for link in links_to_handle_recursive:
                add_all_links_recursive(link, maxdepth=maxdepth - 1)
    
    
    def main():
        add_all_links_recursive(HOST + '/')
        for link in links:
            print(link)
    
    
    if __name__ == '__main__':
        main()
    Ответ написан
    5 комментариев
  • Как спарсить координаты городов?

    trapwalker
    @trapwalker Куратор тега Python
    Программист, энтузиаст
    Попробуйте вытащить данные из базы openstreetmap.
    Снапшот их базы доступен бесплатно.
    Вот есть штука для импорта в posgtres. Надо сказать, что кроме неё есть еще osm2pgsql, который делает примерно то же самое.
    На OSM Wiki можно найти теги, которыми промаркированы точки городов. А дальше вам, возможно, и ваш список названий не нужен будет, там они все (эти города) есть, причем на нескольких языках.

    Вот, кстати, был даже вопрос про фильтрацию на этом ресурсе.
    Ответ написан
    Комментировать