Уведомления

Группа в Telegram: @pythonsu

#1 Авг. 2, 2017 21:33:15

solovs03
Зарегистрирован: 2017-02-15
Сообщения: 27
Репутация: +  0  -
Профиль   Отправить e-mail  

Вопрос по скрапингу...

Учусь собирать инфу по книге “Скрапинг с помощью Python”. Решил сам попрактиковаться, при скрапинге кинопоиска возникло вот такое затруднение:

 from bs4 import BeautifulSoup
from urllib.request import urlopen
import re
spisok = []
URL = urlopen('https://www.kinopoisk.ru/top/')
html = BeautifulSoup(URL, 'lxml')
target = html.find('table', cellspacing='0', cellpadding='3')
for tr in target.findAll('tr'):
    for td in tr:
        try:
            a = td.text
            spisok.append(a)
        except AttributeError:
            continue
print(spisok)

Вывод:
["\n\n\n\xa0\nфильм\n\xa0\n\xa0\n\n\n1.\nПобег из Шоушенка (1994)The Shawshank Redemption\xa0\n\n\n9.197 (428\xa0046)\n\n\n\n\n\xa0\n\n\n\n\n\n2.\nЗеленая миля ….

У меня вопрос. С какой вороньей пи**ы Python соблюдает так много новых строк?(Не знаю как спросить по другому).
Если же не добавлять всё это добро в список а выводить при каждой итерации td то между итерациями tr, 4 или более новых строк (\n).

И ещё вопрос: я конечно понимаю, что со временем благодаря книге я освою хранение информации, но где мне хранить её сейчас? И как это реализовать?




Чтобы чего то достичь нужна - мотивация, и только. (C) Природа

Отредактировано solovs03 (Авг. 2, 2017 21:34:30)

Офлайн

#2 Авг. 2, 2017 21:37:01

solovs03
Зарегистрирован: 2017-02-15
Сообщения: 27
Репутация: +  0  -
Профиль   Отправить e-mail  

Вопрос по скрапингу...

Только заметил, что существует отдельный раздел по вопросам сборам информации, извините новичка за нетерпеливость)0)101)



Чтобы чего то достичь нужна - мотивация, и только. (C) Природа

Офлайн

#3 Авг. 3, 2017 02:21:06

scidam
Зарегистрирован: 2016-06-15
Сообщения: 288
Репутация: +  35  -
Профиль   Отправить e-mail  

Вопрос по скрапингу...

Там очень уж странная table-верстка, куча вложенных таблиц.

Вот пример вывода только названий фильмов.

 from bs4 import BeautifulSoup
from urllib.request import urlopen
import re
spisok = []
URL = urlopen('https://www.kinopoisk.ru/top/')
html = BeautifulSoup(URL, 'lxml')
target = html.select('table table table table')[-1]
for tr in target.findAll('tr'):
    td = tr.findAll('td')[1]
    spisok.append(td.get_text())
print(spisok)
print(len(spisok))

Офлайн

#4 Авг. 3, 2017 03:05:50

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10003
Репутация: +  857  -
Профиль   Отправить e-mail  

Вопрос по скрапингу...

solovs03
У меня вопрос. С какой вороньей пи**ы Python соблюдает так много новых строк?(Не знаю как спросить по другому).
Это дикий текст, он всегда неудобный, и это ещё не самый худший случай. Это только в учебных текстах всегда всё удобно, потому что их готовят для читателей, чтобы они особо не заморачивались, решая задачу. Но это не всегда, конечно; бывают книги и с трудными заданиями (K&R2 - хороший пример, там много диких заданий).

Так что у тебя должно быть два кода: один код скачивает весь текст, который там есть; второй код очищает скачанный текст и приводит его к точному виду. И вот после этого всего ты и работаешь с чистым и удобным текстом.

Учись так делать сразу (разделять процессы), потому что каждый этап может неожиданно оказываться очень сложным. Простое скачивание может требовать посылания дополнительных запросов*. Там могуть оказываться сломанные страницы (браузер отображает, а html-код неправильный и lxml выпадает просто и всё). Обработка текста может требовать умное вырезание внутри, чтобы там удалить какие-нибудь теги, но при этом не удалить ничего лишнего. Поэтому, если тебе кажется, что всё просто и можно это слить воедино, ты потом попадёшь с этой вредной привычкой и будешь всё равно всё переделывать, раскладывая на независимые части.


* У меня так было на YouTube. Вроде просто надо было скачать плейлист и сформировать из него типа таблицы, чтобы потом можно было видео открывать с диска и всю информацию писать о просмотренных роликах (в инете так не сделаешь). Так там для маленьких плейлистов всё работало нормально и легко, но стоило этот скрипт применить к большому плейлисту, как сразу многие видео куда-то пропадали. Когда стал разбираться, оказалось, что YouTube до ста роликов отдаёт нормально, а после ста роликов там используется дополнительный запрос в json'е. Его надо послать на YouTube и тогда он отдаст ролики после ста. То есть пришлось в скрипт встраивать ещё дополнительную проверку на количество роликов и отсылку запроса на дополнительные ролики. Хотя это YouTube, там не должно быть каких-то сюрпризов и костылей.



Отредактировано py.user.next (Авг. 3, 2017 03:08:56)

Офлайн

#5 Авг. 3, 2017 05:27:42

solovs03
Зарегистрирован: 2017-02-15
Сообщения: 27
Репутация: +  0  -
Профиль   Отправить e-mail  

Вопрос по скрапингу...

scidam
Да, это хороший способ вывести текст с одного td, но там в одном tr несколько td и без итерации не обойтись. Да и спрашивал я совсем другое.



Чтобы чего то достичь нужна - мотивация, и только. (C) Природа

Офлайн

#6 Авг. 3, 2017 05:39:03

solovs03
Зарегистрирован: 2017-02-15
Сообщения: 27
Репутация: +  0  -
Профиль   Отправить e-mail  

Вопрос по скрапингу...

py.user.next
Это связано именно с супом или же со всеми модулями парсинга? Насчёт задач это уже совсем другая тема. С детства я считал себя самым тупым в классе, всегда думал что никогда не смогу так быстро схватывать инфу, всё запоминать и т.п пока не понял что эти люди просто кивают головой когда их спрашивают. Задачи всегда были лёгкие, а проблемы с которыми ты сталкиваешься во время решения какой либо задачи были нереально трудные и ты ищешь где найти ответ пока не понимаешь что тебе надо решить задачу самому. Получай Ху*м по лбу. Насчёт очистки текста, очищать с помощью re? Или как?



Чтобы чего то достичь нужна - мотивация, и только. (C) Природа

Офлайн

#7 Авг. 3, 2017 06:49:41

py.user.next
От:
Зарегистрирован: 2010-04-29
Сообщения: 10003
Репутация: +  857  -
Профиль   Отправить e-mail  

Вопрос по скрапингу...

solovs03
Это связано именно с супом или же со всеми модулями парсинга?
Это на сайте так написано. Твоя задача - выбрать оттуда всё без потерь. Потом это “сырьё” обработать, чтобы получить очищенный материал (текст, без лишних символов). И дальше ты уже работаешь с этим материалом.

solovs03
Насчёт очистки текста, очищать с помощью re?
Очищать надо алгоритмически, где-то это re, где-то это цикл с перебором всех символов и выборкой только нужных. Да и, бывает, что нужно применять всё вместе и чистить в несколько проходов.

В данном случае ты бы мог все группы небуквенных символов сжать до одного символа.

  
>>> import re
>>> 
>>> def clear_string(s):
...     out1 = re.sub(r'\s+', ' ', s)
...     out2 = out1.strip()
...     return out2
... 
>>> text = ('\n\n\n\xa0\nфильм\n\xa0\n\xa0\n\n\n1.\n'
...         'Побег из Шоушенка (1994)The Shawshank Redemption'
...         '\xa0\n\n\n9.197 (428\xa0046)\n\n\n\n\n\xa0\n\n\n'
...         '\n\n\n2.\nЗеленая миля')
>>> 
>>> out = clear_string(text)
>>> out
'фильм 1. Побег из Шоушенка (1994)The Shawshank Redemption 9.197 (428 046) 2. Зеленая миля'
>>>



Отредактировано py.user.next (Авг. 3, 2017 06:50:23)

Офлайн

#8 Авг. 3, 2017 14:33:19

Vintets
Зарегистрирован: 2016-07-05
Сообщения: 41
Репутация: +  6  -
Профиль   Отправить e-mail  

Вопрос по скрапингу...

solovs03
С какой вороньей пи**ы Python соблюдает так много новых строк?(Не знаю как спросить по другому).
Ты их сам добавляешь.
Ведь ты проходишься циклом по всем вложенным ‘td’ и добавляешь странный параметр ‘.text’. Я такой параметр в документации не нашёл.
В объекте Tag текст берётся через
 a = td.string
По td.string можно взять строку текста только объекта td, а у нас куча вложенных тэгов <div><a> и прочие <span> и текст на разном уровне.

Значит нужно искать и перебирать не ‘td’, а любые теги в которых есть string. Сразу исключать, если строка состоит из одного пробела , неразрывного пробела или перевода строки.
Заодно сразу поделить по фильмам.
 target = html.findAll('table', cellspacing='0', cellpadding='3')
for tr in target[1].findAll('tr'):
    film = []
    for link in tr.findAll(text=True):
        a = link.string
        if a not in [u' ', u' ', u'\n']:
            film.append(a)
    spisok.append(film)
    print json.dumps(film, ensure_ascii=False).encode('cp866', 'ignore')
# print json.dumps(spisok, ensure_ascii=False).encode('cp866', 'ignore')

Получим
["фильм"]
["1.", "Побег из Шоушенка (1994)", "The Shawshank Redemption", "9.197", "(427 755)"]
["2.", "Зеленая миля (1999)", "The Green Mile", "9.148", "(407 218)"]
["3.", "Форрест Гамп (1994)", "Forrest Gump", "9.001", "(400 387)"]
["4.", "Список Шиндлера (1993)", "Schindler's List", "8.895", "(215 120)"]
["5.", "1+1 (2011)", "Intouchables", "8.866", "(415 927)"]
...

В более новой версии (у меня старая) есть ещё stripped_strings, который сам уже будет удалять лишние переводы строк и пробельные строки.

Офлайн

#9 Авг. 3, 2017 19:13:11

solovs03
Зарегистрирован: 2017-02-15
Сообщения: 27
Репутация: +  0  -
Профиль   Отправить e-mail  

Вопрос по скрапингу...

Vintets
Я писал в начале, то что я новичок в этой сфере и учусь по книге.

Vintets
… и добавляешь странный параметр ‘.text’.
Vintets
for link in tr.findAll(text=True): …
Вы определили его, а значит он имеется почти у каждого тега - в моём случае, а если он не имеется, для него заготовлен обработчик исключений, хотя и можно было воспользоваться конструкцией if…

Каждый парсит по своему, я всего лишь пытаюсь найти свой стиль, у меня ваш код c поправками для 3.5 ветки - вообще вывел:
minator 2: Judgment Day', ‘\xa0’, ‘8.367’, ‘(233\xa0804)’, ‘6’, ‘\xa0’], , , , , ,

И прочую неразбириху. А по какой книгу учились вы, если не секрет?



Чтобы чего то достичь нужна - мотивация, и только. (C) Природа

Офлайн

#10 Авг. 3, 2017 19:15:20

solovs03
Зарегистрирован: 2017-02-15
Сообщения: 27
Репутация: +  0  -
Профиль   Отправить e-mail  

Вопрос по скрапингу...

Vintets
Насчёт string, там можно многими способами вытащить данные между тегами, есть и get_text и моим методом - с помощью параметра text и т.д



Чтобы чего то достичь нужна - мотивация, и только. (C) Природа

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version