Closed trin4ik closed 2 months ago
Вроде готово. Из сделанного:
posts/management/commands
Парсинг приватных и комментов сделал через апки (https://vas3k.club/apps/). Учитывая, как часто последнее время меняется вёрстка комментов, идея с парсингом html страниц быстро отпала. С другой стороны, разрабу нужно один раз зарегать аппку, указать токен при запуске команды и вуаля, более подробные данные о пользователях, приватные посты и комменты сразу доступны. Просто и безопасно. Столкнулся с тем, что иногда комменты имеют какой-то глюк с created_at. Когда дата создания ответа почему-то раньше, чем дата создания основного комментария. Это вызывает ошибку foreign key, т.к. пытаемся создать ответ на коммент, которого ещё не существует. Не стал долго разбираться, просто воткнул
connection = connections['default']
with connection.cursor() as cursor:
cursor.execute('SET session_replication_role TO \'replica\';')
Учитывая, что это только на выполнение скрипта, проблем с этим не вижу. Ну и поменял немного вывод в консоли, добавил традиционный тако
Готово 🌮
📄 Новых постов: 203
📌 Уже существовало: 21
📝 Отредактировано: 0
👤 Новых пользователей: 66
💬 Новых комментов: 12954
Теперь появилась другая проблема, пока тестил, постоянно путался, где страница клуба, а где локальная версия.
для скорости: замени urllib на requests /пакет уже в проекте/ и создавай запросы с одной сессией.
service_token запиши в .env, чтоб не вводить каждый раз /см. dotenv в settings проекта/
Насчёт времени комментов: они отличаются на равное количество часов? Или бывает что на пару минут? Проект не юзает враппер Django для дат, возможно, в этом проблема.
Не надо так:
def parse_comments(post_id, url):
for comment in data['comments']:
if not Comment.objects.filter(id=comment['id']).exists():
create_user(comment['author'])
comments.append(Comment(
...
))
Comment.objects.bulk_create(comments, 100)
Не делай запросы к базе внутри циклов, т.к. Django лениво подгружает данные и насилует её на каждой итерации.
У метода bulk_create доступна опция "ignore_conflicts". С ней не нужно проверять существует ли Comment — база сама проигнорирует дубликаты: Comment.objects.bulk_create(comments, ignore_conflicts=True, batch_size=100)
см: https://docs.djangoproject.com/en/5.0/ref/models/querysets/#bulk-create
Теперь появилась другая проблема, пока тестил, постоянно путался, где страница клуба, а где локальная версия.
Специально для тебя написал расширение для Хрома. Не благодари :-) vitalik_eto_dev.zip
Какие люди )
- для скорости: замени urllib на requests /пакет уже в проекте/ и создавай запросы с одной сессией.
Ага, надо будет переделать. На самом деле нет задачи сильно ускориться, т.к. в таком случае можно упереться в лимит запросов.
- service_token запиши в .env, чтоб не вводить каждый раз /см. dotenv в settings проекта/
Тоже как варик ага, проверять dotenv параллельно с аргументами, однако если у тебя несколько веток, то это условно бесполезно. Т.е. какая разница, что создавать .env, что прокинуть в параметры. Если же контрибьютор работает в основном с одной версией проекта, т.е. физически с одной директорией, то смыл в этом есть.
- Насчёт времени комментов: они отличаются на равное количество часов? Или бывает что на пару минут? Проект не юзает враппер Django для дат, возможно, в этом проблема.
Если это про глюк времени, я думаю это связано с удалёнными комментами. Почему именно так происходит разбираться лениво, да и в целом решение со временным отключением foreign keys вполне норм.
- Не надо так:
def parse_comments(post_id, url): for comment in data['comments']: if not Comment.objects.filter(id=comment['id']).exists(): create_user(comment['author']) comments.append(Comment( ... )) Comment.objects.bulk_create(comments, 100)
Не делай запросы к базе внутри циклов, т.к. Django лениво подгружает данные и насилует её на каждой итерации.
Про ignore_conflicts в тему, надо поправить. Но в целом точечные запросы по первичному индексу в локальной базе на пару тысяч записей -- это не проблема. Т.е. в рамках данной задачи, зная что код будет запускаться только в dev/local у разраба с пустой базой, можно не обращать внимание на подобное.
Да-да, я теперь в секте освободивших Джнаго)
Добавь import requests, скопируй всё из класса Parser в свой класс и используй:
try:
# Request page
page = self.get_page('http://example.com/api/v1/')
# Do what you need with result
except ConnectionError as error:
# Handle errors, e.g.:
# return self.stdout.write(self.style.ERROR(error))
В лимит едва ли упрёшься, для этого как минимум нужны асинхронные запросы)
Т.е. какая разница, что создавать .env, что прокинуть в параметры.
- Дело не только в удобстве: с API ключами нужно обращаться как с паролями, ты это лучше меня понимаешь) Сейчас консоль их логирует в чистом виде, а ещё Джанго может отправить на сервер-сборщик логов /он подключён в проекте/.
Если это про глюк времени, я думаю это связано с удалёнными комментами. Почему именно так происходит разбираться лениво, да и в целом решение со временным отключением foreign keys вполне норм.
Глянул модель комментов, она при удалении ставит флаг и обновляет время updated_at. Время created_at ставится только при создании. Может API выдаёт дату изменения, а не создания?..
В рамках задачи — не спорю, не критично. Но теперь ты знаешь про ошибку и будешь писать код чуточку лучше)
Работа над ошибками:
authn/management/commands
вposts/management/commands
Публикую как драфт, хочу добавить ещё флаг
--with-comments
, для поиска он пригодится.