[Python, API] Сохраняем комментарии youtube в csv
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
ПредысторияКак-то на одном youtube канале, устроили розыгрыш среди комментаторов.Условием было угадать цену закрытия акций хотя бы одной из трёх конкретных компаний.Мне стало интересно собрать статистику за какие цены пользователи голосовали больше других и сработал ли "коллективный разум", когда пусть каждый отдельно взятый голос был далёк от истины, но среднее значение голосов внезапно попадало в точку.Плюс задача сбора статистики усложнялась тем, что комментарии написаны в единое текстовое поле, а не в форму, где все значения на своих местах и нужного типа. Заспойлерю: распарсить комментарии оказалось самой трудоёмкой задачей, потому что не было даже единой схемы ответа (ок была превалирующая, но далеко не единственная):
- одни писали сначала название компании потом цену, другие -- наоборот цену, потом компанию (кое-кто писал название, много вводных слов обосновывающих его мысли и потом цену)
- Где-то было название, где-то тикер
- Местами текст был на английском, местами на русском
- Дробные части отделяли и точками и запятыми
- Встречались и опечатки в несколько букв (в одном слове)
- Многие сокращали название до двух букв, сочетание которых очевидно встречалась и в обычных комментариях, не связанных с конкурсом
- Были и жаргонные названия компаний (Бумер вместо BMW), и наоборот полные (Bayerische Motoren Werke)
- Но призёрами в борьбе с парсингом стали люди, писавшие в словах Tesla и BMW - русскую букву "т" и русскую "в" в начале слова, а дописывавшие его английскими буквами (последнее заметил по чистой случайности просматривая json содержимое, когда латиница идёт буквами, а весь юникод заменяется слешами с кодами)
Для чего эта статья? Ведь есть платные парсеры / документация на Yotube APIВо-первых, не все хотят платить за то, что можно получить бесплатно.Во-вторых, не у всех хорошо с английским, да и зачем курить длинные мануалы, если задача узкая и односложная.В-третьих, никакой похожей инструкции на первой странице поиска не нашлось, думаю это нужно исправить.Чтобы инструкция была более гибкой и её можно было использовать, даже если что-то изменится в одном из шагов, в каждом оставлю источники.
- Получите ключ для работы с youtube API (источник)
- Возьмитие ваш гугл-аккаунт и создайте проект по ссылке https://console.developers.google.com/
- На странице разрешений https://console.developers.google.com/apis/credentialsСоздайте новый API ключ
(Сохраните его, чтобы потом не искать)
- На главной https://console.cloud.google.com/apis/dashboardПерейдите к странице включения сервисов для API
- Найдите YouTube Data API v3
- Включите его
- Получите библиотеку google-api-python-client (источник)
- Возьмите python
- Выполните командуpip.exe install google-api-python-client
- Запустите скрипт
- Возьмите редактор, например visual studio code
- Создайте новый python файл и вставьте в него следующий кодВсё что вам нужно в нём поправить для старта это
- DEVELOPER_KEY -- получен в первом пункте
- VIDEO_ID -- берётся из ссылки на видео, например в ссылке https://youtu.be/9b4-G-czN5Y нас интересует 9b4-G-czN5Y
# -*- coding: utf-8 -*-
import os
import googleapiclient.discovery
import csv
DEVELOPER_KEY = "AIzaSyB7oKxIsd4690TibZHZPaTLzw7nqzgrr4k"
VIDEO_ID = "9b4-G-czN5Y"
# Функция для скачивания корневых комментариев
def youtube(nextPageToken=None):
# Disable OAuthlib's HTTPS verification when running locally.
# *DO NOT* leave this option enabled in production.
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
api_service_name = "youtube"
api_version = "v3"
youtube = googleapiclient.discovery.build(
api_service_name, api_version, developerKey = DEVELOPER_KEY)
request = youtube.commentThreads().list(
part="id,snippet",
maxResults=100,
pageToken=nextPageToken,
videoId=VIDEO_ID
)
response = request.execute()
return response
# Функция для скачивания реплаев на комментарии
def youtubechild(NextParentId, nextPageToken=None):
# Disable OAuthlib's HTTPS verification when running locally.
# *DO NOT* leave this option enabled in production.
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
api_service_name = "youtube"
api_version = "v3"
youtube = googleapiclient.discovery.build(
api_service_name, api_version, developerKey = DEVELOPER_KEY)
request = youtube.comments().list(
part="id,snippet",
maxResults=100,
pageToken=nextPageToken,
parentId=NextParentId
)
response = request.execute()
return response
# Главная функция
def main():
# Скачиваем комментарии
print('download comments')
response = youtube()
items = response.get("items")
nextPageToken = response.get("nextPageToken") # скачивается порциями, на каждую следующую выдаётся указатель
i=1
while nextPageToken is not None:
print(str(i*100)) # показываем какая сотня комментариев сейчас скачивается
response = youtube(nextPageToken)
nextPageToken = response.get("nextPageToken")
items = items + response.get("items")
i+=1
print(len(items)) # Отображаем количество скачаных комментариев
# Скачиваем реплаи на комментарии
print('download replies')
replies = []
for line in items: # Проходим по корневым комментам
if line.get("snippet").get("totalReplyCount") > 0: # если есть реплаи
print(line.get("snippet").get("totalReplyCount")) # показываем сколько реплаев будет подгружено
response = youtubechild(line.get("snippet").get("topLevelComment").get("id"))
replies = replies + response.get("items")
nextPageToken = response.get("nextPageToken")
i=1
while nextPageToken is not None: # догружаем реплаи, если есть ещё порции
response = youtubechild(line.get("snippet").get("topLevelComment").get("id"), nextPageToken)
nextPageToken = response.get("nextPageToken")
replies = replies + response.get("items")
i+=1
print(len(replies)) # Отображаем количество скачаных реплаев
# Сохраняем комментарии и реплаи на них в файл csv
print("Open csv file")
with open('youtuberesults.csv', 'w', encoding="utf-8") as csv_file: #конструкция with, чтобы файл закрылся автоматом после всех команд
writer = csv.writer(csv_file, quoting=csv.QUOTE_ALL, lineterminator='\r') # использовал двойные кавычки и разделитель запятую, такой формат отлично открывается через LibreOffice Calc
# Заголовки столбцов
row = [
'etag'
, 'parentid'
, 'id'
, 'textDisplay'
, 'textOriginal'
, 'authorDisplayName'
, 'authorProfileImageUrl'
, 'authorChannelUrl'
, 'authorChannelId'
, 'likeCount'
, 'publishedAt'
, 'updatedAt'
]
print("Start write in csv")
writer.writerow(row) # Записываем заголовки в файл
# Сохраняем комментарии
print("Write comments in csv")
for line in items:
topLevelComment = line.get("snippet").get("topLevelComment")
# бывает, что у пользователя нет канала, поэтому для него отдельная конструкция
if topLevelComment.get('snippet').get('authorChannelId') is not None:
authorChannelId = topLevelComment.get('snippet').get('authorChannelId').get('value')
else:
authorChannelId = ''
row = [
topLevelComment.get('etag')
, topLevelComment.get('id')
, topLevelComment.get('id')
, topLevelComment.get('snippet').get('textDisplay')
, topLevelComment.get('snippet').get('textOriginal')
, topLevelComment.get('snippet').get('authorDisplayName')
, topLevelComment.get('snippet').get('authorProfileImageUrl')
, topLevelComment.get('snippet').get('authorChannelUrl')
, authorChannelId
, topLevelComment.get('snippet').get('likeCount')
, topLevelComment.get('snippet').get('publishedAt')
, topLevelComment.get('snippet').get('updatedAt')
]
writer.writerow(row)
# Сохраняем реплаи
print("Write replies in csv")
for line in replies:
# бывает, что у пользователя нет канала, поэтому для него отдельная конструкция
if line.get('snippet').get('authorChannelId') is not None:
authorChannelId = line.get('snippet').get('authorChannelId').get('value')
else:
authorChannelId = ''
row = [
line.get('etag')
, line.get('snippet').get('parentId')
, line.get('id')
, line.get('snippet').get('textDisplay')
, line.get('snippet').get('textOriginal')
, line.get('snippet').get('authorDisplayName')
, line.get('snippet').get('authorProfileImageUrl')
, line.get('snippet').get('authorChannelUrl')
, authorChannelId
, line.get('snippet').get('likeCount')
, line.get('snippet').get('publishedAt')
, line.get('snippet').get('updatedAt')
]
writer.writerow(row)
print("done")
if __name__ == "__main__":
main()
В полученной таблице все поля, которые доступны по YouTube API. Созданный csv отлично открывается в LibreOffice Calc. Используются двойные кавычки и разделитель запятая, кодировка UTF-8. Если нужно отличить корневой комментарий от реплая можно добавить столбец с сравнением parentid с id - в случае их равенства комментарий корневой, иначе реплай.
===========
Источник:
habr.com
===========
Похожие новости:
- [API, Разработка под e-commerce, Управление e-commerce] Как продавать на маркетплейсе, не вздрагивая при слове «инфообмен»
- [Информационная безопасность, Разработка веб-сайтов, API, Тестирование веб-сервисов] Nemesida WAF 2021: защита сайтов и API от хакерских атак
- [Laravel] Проверка тестов PHP API на соответствие определениям OpenAPI — пример Laravel
- [Python, Машинное обучение] Эволюция OLEG AI. Нейросеть, утечки памяти, нагрузка
- [Python, Алгоритмы, Big Data, Машинное обучение, Искусственный интеллект] Data Phoenix Digest — 01.07.2021
- [Разработка мобильных приложений, Здоровье, IT-компании] Google завела на Android прививочные карточки с QR-кодами
- [Python, Алгоритмы, Big Data, Машинное обучение, Искусственный интеллект] Data Phoenix Digest — 01.07.2021
- [Java, IT-компании] Spring MVC vs Spring WebFlux. Что лучше? Объясняем на пингвинах
- [JavaScript, Maps API, ReactJS] Использование mapbox-gl в React и Next.js
- [Мессенджеры, Поисковые технологии, Управление медиа, Социальные сети и сообщества] Закон о «приземлении» иностранных интернет-порталов
Теги для поиска: #_python, #_api, #_youtube, #_kommentarii (комментарии), #_python, #_api
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 11:50
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
ПредысторияКак-то на одном youtube канале, устроили розыгрыш среди комментаторов.Условием было угадать цену закрытия акций хотя бы одной из трёх конкретных компаний.Мне стало интересно собрать статистику за какие цены пользователи голосовали больше других и сработал ли "коллективный разум", когда пусть каждый отдельно взятый голос был далёк от истины, но среднее значение голосов внезапно попадало в точку.Плюс задача сбора статистики усложнялась тем, что комментарии написаны в единое текстовое поле, а не в форму, где все значения на своих местах и нужного типа. Заспойлерю: распарсить комментарии оказалось самой трудоёмкой задачей, потому что не было даже единой схемы ответа (ок была превалирующая, но далеко не единственная):
# -*- coding: utf-8 -*-
import os import googleapiclient.discovery import csv DEVELOPER_KEY = "AIzaSyB7oKxIsd4690TibZHZPaTLzw7nqzgrr4k" VIDEO_ID = "9b4-G-czN5Y" # Функция для скачивания корневых комментариев def youtube(nextPageToken=None): # Disable OAuthlib's HTTPS verification when running locally. # *DO NOT* leave this option enabled in production. os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1" api_service_name = "youtube" api_version = "v3" youtube = googleapiclient.discovery.build( api_service_name, api_version, developerKey = DEVELOPER_KEY) request = youtube.commentThreads().list( part="id,snippet", maxResults=100, pageToken=nextPageToken, videoId=VIDEO_ID ) response = request.execute() return response # Функция для скачивания реплаев на комментарии def youtubechild(NextParentId, nextPageToken=None): # Disable OAuthlib's HTTPS verification when running locally. # *DO NOT* leave this option enabled in production. os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1" api_service_name = "youtube" api_version = "v3" youtube = googleapiclient.discovery.build( api_service_name, api_version, developerKey = DEVELOPER_KEY) request = youtube.comments().list( part="id,snippet", maxResults=100, pageToken=nextPageToken, parentId=NextParentId ) response = request.execute() return response # Главная функция def main(): # Скачиваем комментарии print('download comments') response = youtube() items = response.get("items") nextPageToken = response.get("nextPageToken") # скачивается порциями, на каждую следующую выдаётся указатель i=1 while nextPageToken is not None: print(str(i*100)) # показываем какая сотня комментариев сейчас скачивается response = youtube(nextPageToken) nextPageToken = response.get("nextPageToken") items = items + response.get("items") i+=1 print(len(items)) # Отображаем количество скачаных комментариев # Скачиваем реплаи на комментарии print('download replies') replies = [] for line in items: # Проходим по корневым комментам if line.get("snippet").get("totalReplyCount") > 0: # если есть реплаи print(line.get("snippet").get("totalReplyCount")) # показываем сколько реплаев будет подгружено response = youtubechild(line.get("snippet").get("topLevelComment").get("id")) replies = replies + response.get("items") nextPageToken = response.get("nextPageToken") i=1 while nextPageToken is not None: # догружаем реплаи, если есть ещё порции response = youtubechild(line.get("snippet").get("topLevelComment").get("id"), nextPageToken) nextPageToken = response.get("nextPageToken") replies = replies + response.get("items") i+=1 print(len(replies)) # Отображаем количество скачаных реплаев # Сохраняем комментарии и реплаи на них в файл csv print("Open csv file") with open('youtuberesults.csv', 'w', encoding="utf-8") as csv_file: #конструкция with, чтобы файл закрылся автоматом после всех команд writer = csv.writer(csv_file, quoting=csv.QUOTE_ALL, lineterminator='\r') # использовал двойные кавычки и разделитель запятую, такой формат отлично открывается через LibreOffice Calc # Заголовки столбцов row = [ 'etag' , 'parentid' , 'id' , 'textDisplay' , 'textOriginal' , 'authorDisplayName' , 'authorProfileImageUrl' , 'authorChannelUrl' , 'authorChannelId' , 'likeCount' , 'publishedAt' , 'updatedAt' ] print("Start write in csv") writer.writerow(row) # Записываем заголовки в файл # Сохраняем комментарии print("Write comments in csv") for line in items: topLevelComment = line.get("snippet").get("topLevelComment") # бывает, что у пользователя нет канала, поэтому для него отдельная конструкция if topLevelComment.get('snippet').get('authorChannelId') is not None: authorChannelId = topLevelComment.get('snippet').get('authorChannelId').get('value') else: authorChannelId = '' row = [ topLevelComment.get('etag') , topLevelComment.get('id') , topLevelComment.get('id') , topLevelComment.get('snippet').get('textDisplay') , topLevelComment.get('snippet').get('textOriginal') , topLevelComment.get('snippet').get('authorDisplayName') , topLevelComment.get('snippet').get('authorProfileImageUrl') , topLevelComment.get('snippet').get('authorChannelUrl') , authorChannelId , topLevelComment.get('snippet').get('likeCount') , topLevelComment.get('snippet').get('publishedAt') , topLevelComment.get('snippet').get('updatedAt') ] writer.writerow(row) # Сохраняем реплаи print("Write replies in csv") for line in replies: # бывает, что у пользователя нет канала, поэтому для него отдельная конструкция if line.get('snippet').get('authorChannelId') is not None: authorChannelId = line.get('snippet').get('authorChannelId').get('value') else: authorChannelId = '' row = [ line.get('etag') , line.get('snippet').get('parentId') , line.get('id') , line.get('snippet').get('textDisplay') , line.get('snippet').get('textOriginal') , line.get('snippet').get('authorDisplayName') , line.get('snippet').get('authorProfileImageUrl') , line.get('snippet').get('authorChannelUrl') , authorChannelId , line.get('snippet').get('likeCount') , line.get('snippet').get('publishedAt') , line.get('snippet').get('updatedAt') ] writer.writerow(row) print("done") if __name__ == "__main__": main() =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 11:50
Часовой пояс: UTC + 5