Pull to refresh

Comments 48

Вопрос.
Допустим у нас ряд ссылок динамически формируются с помощью JS, т.е. мы их не можем получить во время парсинга. А они нам нужны для перехода парсера по страничкам. Что делать?
Рендерить с помощью selenium, phantomjs и т.п. или разбираться как js их формирует (допустим выяснили что ссылки получают ajax запросом, делаем подобный запрос и парсим его). У каждого метода свои плюсы и минусы, какой использовать зависит уже от конкретного задания.
с помощью selenium

Не вариант. Мелькание браузера и непонятно что происходящего с ним может очень здорово испугать пользователя. Я как-то автоматизировал одному человеку с помощью Selenium и ChromeDriver-а. Так меня потом человек раз 5 спрашивал, а его браузер не испорится ли случайно? ;)))
а причем тут пользователи?
Как уже было написано ниже, в большинстве случае если смысл посмотреть какие запросы делает браузер, и понять, каким образом JS заполняет сайт. Второй вариант — Selenium. Его совсем необязательно использовать в оконном режиме, к примеру: headless firefox
к примеру: headless firefox

Спасибо. Посмотрю!
Отлично работает связка из Selenium + PhantomJS. Ничего не мелькает и при этом всё делает.
P.S. Долго читал, медленно отвечал.
Использовать Phantomjs либо Selenium webdriver
использовать Selenium. позволяет подключать драйвер как реального (Chrome, Firefox, IE) так и виртуального (Phantom JS) браузера и через этот «браузер» получать динамически формируемые данные.
Эмулятор браузера вам нужен — Selenium, например. Но скорость парсинга, конечно, упадет — сами понимаете.
Да, с R&C аккаунтом чувствуешь себя идиотом: после одобрения комментария оказывается, что точно такой же ответ дали еще трое человек до тебя и столько же — после, а опубликовалось все это оптом.
Так напишите статейку, избавьтесь от проблем.)
И использовать selenium вместе с phantomjs. Пример
Можно использовать Selenium или phantom.js для исполнения скриптов.
UFO just landed and posted this here
Для Scrapy можно попробовать scrapyjs. Чем и займусь в ближайшее время…
UFO just landed and posted this here
Из опыта могу сказать что в каждом случае подход индивидуальный. Зависит от сайта — иногда ссылка есть, но не прямо в href/src. Иногда можно понять правило ее формирования, иногда можно запросить API сайта и получить ссылку там. Иногда комбинируется несколько вариантов. Т.е. производится своеобразный реверс-инжиниринг сайта.
В особо тяжелых случаях придется использовать (как писали выше) реальный браузер или же эмулятор, но такие на моей практике встречались нечасто.
Не осветили двух важных вопросов:
  1. Авторизация на сайте. Популярные по логину и паролю, и oauth2
  2. Не осветили вопроса вбивания данных в контролы на странице, к примеру на странице может быть Combobox для выбора города. Или Edit для ввода возраста. Тажке часто встречается снять\выделить галочку и т.д. и т.п.
Отвечу на второй вопрос. Такие контролы либо перезагружают страницу и тогда мы можем получить адрес, либо грузят дополнительные данные по Ajax, тогда нам совсем просто.
USERNAME = input('Введите вашу почту: ')
PASSWORD = input('Введите ваш пароль: ')

LOGIN_URL = "***" # Страница Логина
URL = "***" # Страница самого контента для парсинга

session_requests = requests.session()

def parse_one():

            # Create payload
    payload = {
        "email": USERNAME,
        "password": PASSWORD
    }

    # Perform login
    result = session_requests.post(LOGIN_URL, data = payload, headers = dict(referer = LOGIN_URL))

    # Scrape journal_url
    result = session_requests.get(URL, headers = dict(referer = URL))
    soup = BeautifulSoup(result.content)

вот так можно пройти логин, сохранить данные в сессию, перейти к странице контента, используя данные сессии.
Я не про то что я не знаю. Я бы поленился подобный вопрос задавать, а просто и тупо вбил в гугл "python authentication to website", что привело бы меня к страничке на SO.
Прочитайте внимательно формулировку предложений! Она звучит не "А не подскажите как сделать авторизацию?", нет, она звучит по-другому: "не раскрыты важные вопросы.
По опыту могу сказать, что очень много людей ищущих ответы на вопросы в гугле не читаю больше чем 2-3 комментариев к статье, если вообще читают. Поэтому подобные вопросы должны освещаться непосредствено в самой статье!
Мне показалось, что автор хочет передать знания, значит нужно осветить как можно больше важных вопросов, которые очень часто встают перед новичком. Если же автор ленится, то это уже не желание научить, а попытка сказать "смотрите какой я крутой".
Спасибо, действительно эти темы могут пригодиться при решении задач Web Scrapping'a — добавила в статью.
Для парсинга веб-страниц есть отличный фреймворк Grab. На Хабре были статьи о нём от автора.
Если скрэппинг нужен не на регулярной основе (например когда сервер постоянно откачивает чужой контент), а для разовой или периодических задач, когда можно запустить скрипт вручную, то мне гораздо быстрее и проще написать JS скрипт с использованием jQuery и запустить его прямо из командной строки инспектора. Тогда уже будет и правильный юзер агент и решена проблема с авторизацией и вообще проблем будет меньше.
Lxml получается быстрее? А если использовать beautifulsiup с бекэндом lxml разница остаётся ?
Стоит отметить, что BeautifulSoup выбирает оптимальный парсер из установленных:
If you don’t specify anything, you’ll get the best HTML parser that’s installed. Beautiful Soup ranks lxml’s parser as being the best, then html5lib’s, then Python’s built-in parser
(источник)

Я измерила время работы на своих данных и в среднем получила такие цифры
bs_html_parser: 0.43 секунды
bs_lxml_parser: 0.43 секунды (значимой разницы между lxml и python's default html-parser в BS на своих данных я не вижу)
lxml: 0.05 секунд (lxml явно выигрывает)
Я бы ещё потребление памяти померил.
В целом тема интересная, но конкретно вашу задачу можно решить чуть проще.
По ссылке httр://www.kinopoisk.ru/user/<user_id>/votes/list/export/xls/vs/vote/ оно вернёт вам xls файл со всей необходимой информацией (и даже больше чем нужно).
Правда, в новом кинопоиске такую замечательную возможность выпилили. Там нужно либо извращаться, либо не пользоваться.
У меня даже где-то shell скрипт закронен, чтобы скачивать его раз в неделю (после осенних событий я им больше так не доверяю, как это было раньше).
Вот это действительно полезно. Как вы об этой ссылке узнали? Что-то еще подобное-полезное есть?
(ps. кажется, у вас в ссылке p в http русская, вот корректная ссылка — http://www.kinopoisk.ru/user/<user_id>/votes/list/export/xls/vs/vote/)
Эта ссылка доступна всем желающим авторизованным пользователям на странице собственного профиля :)
http://www.kinopoisk.ru/user/<user_id>/votes/ > прямо под ником там есть ссылка "экспорт в MS Excel".
Еще есть в открытом доступе ссылка, для получения рейтинга фильма или сериала:
http://rating.kinopoisk.ru/{{kinopoisk_id}}.xml
Вместо {{kinopoisk_id}} просто подставьте нужный ID. Например, для Зверополиса — http://www.kinopoisk.ru/film/775276/ — вам нужно подставить в ссылку id 775276
Еще есть вот такой сервис с API для Кинопоиска — http://kinopoisk.cf/, узнал про него в свое время с Тостера
with open('test.html', 'w') as output_file:
  output_file.write(r.text.encode('cp1251'))

А почему вы явно указываете кодировку?
Requests возвращает ответ в виде Unicode
isinstance(r.text, unicode) # True

При попытке записать unicode строку в файл по умолчанию будет использована кодировка ASCII и ничего не получится (ASCII не может закодировать символы >128):
UnicodeEncodeError: 'ascii' codec can't encode characters in position 23-31: ordinal not in range(128).
Вот поэтому я явным образом указываю кодировку cp1251.

Если интересно, подробнее про кодировки в Python есть хорошая статья на Хабре.
Я про хардкод. Ведь можно же спросить про кодировку у пришедшего ответа. Если использовать urllib, то это как-то так:
>>> from urllib.request import urlopen
>>> URL = 'http://habrahabr.ru'
>>> page = urlopen(URL)
>>> page.info().get_content_charset()
'utf-8'
>>> charset = page.info().get_content_charset()
>>> document = page.read().decode(charset)
Снят Вопрос.
Не внимательно читаю код, в упор не видел вызова "save".
Вы же пишите, тогда все логично ;)))
UFO just landed and posted this here
Да, верно: в полноценной production версии пришлось бы обвешать код дополнительными проверками на наличие тегов/атрибутов и обрабатывать exceptional cases
Если честно не понятно о чем статья. О том, что такое xpath и как парсить html есть целая куча статей. О том же scrapy и grab есть статьи на хабре.

Вот если бы в статье рассматривались какие-то хитрые обходы блокировок сайтов от роботов, ну или хотя бы была раскрыта тема подмены прокси, куков, referrer. А тут извините очень банально все.
Если ограничивать авторов в темах требованием писать всё более и более хардкорные вещи, пишущих авторов будет становится всё меньше и меньше.
Данная статья имеет свою целевую аудиторию — тех людей, кто не является профи в разборе страниц сайтов и хочет с чего-то начать. То, что вы не относитесь к этой категории, делает статью "банальной" лишь для вас.
Возможно, стоило делать запросы к Kinopoisk в несколько потоков? Однопоточная версия скрипта не самая быстрая.
Да, Вы правы, это могло бы ускорить время выгрузки данных, но тут нужно пробовать: сайт может забанить за слишком частые запросы с одного IP.
Сайту ничего не мешает вас забанить и при запросах в один поток. Всё упирается в разумную паузу между отправкой запросов или пачками запросов (скажем, отправляем N запросов, засыпаем на M секунд, снова отправляем и т.д.).
Я, кстати, когда парсил кинопоиск, тоже был забанен за частые запросы =) Но голь на выдумку хитра. Чтобы это обойти, банально нужно авторизоваться на нем, плюс сохранить куки. В итоге в один поток парсил лимитировано по 150 сериалов за запрос, включая всю информацию по сезонам и эпизодам. Ничего, живем :)
Вот с afisha.mail.ru такое не прокатило(( Пришлось купить 3 персональных анонимных проксика, и уже с ними, рандомно выбирая при каждом запросе один из них, маилру тоже поддался и пропали баны за многократное обращение =)
Для imhonet нового никто не писал выгрузку своих оценок фильмов\книг?
Спасибо за комментарий и замечание, поправила название.
Sign up to leave a comment.

Articles