2 место Парсинг открытой информации с YouTube через APIv3 в MySQL

BAZAg

Client
Регистрация
08.11.2015
Сообщения
418
Благодарностей
554
Баллы
93
1.jpg

Здравствуйте!
Меня зовут Юрий Йосифович.
Живу в селе и в реальной жизни не работаю.
Если бы мне кто-то когда-то сказал, что я буду одалживать кучу денег на покупку лицензии на какую-то программу - я бы спросил этого человека, что он курил...
Но... Все меняется! В один день я взял калькулятор и подсчитал свой суточный заработок с iMacros. Умножил данное число на 10. И тогда я понял, что если сейчас найду деньги на Зеннопостер, то у меня появится "палка-копалка" которая будет приносить деньги в несколько раз быстрее. Если же не рискну - то так и буду топтаться в копеечных заработках. В результате - я одолжил денег и уже 9 ноября 2015 года вступил в ряды сообщества счастливых обладателей программ от ZennoLab.

Первые несколько дней я разбирался с тем как установить программы и как писать первые шаблоны и уже через месяц с момента покупки я окупил вложения в лицензии и прокси.
Сразу пришла мысль масштабировать доход - был куплен еще один комплект (ZennPosterPRO + CapMonstr2)... И так в течении пол года я стал обладателем 6 лицензий на Зеннопостер ПРО и прокачал КапМонстр2 до 180 потоков и окупил вложения.

У меня есть свой блог, есть канал на YouTube - там я и стараюсь сделать так, чтобы о данных программах узнало как можно больше людей. Кому-то рассказываю, зачем ему Зеннопостер, кому-то - как написать шаблон, кому-то как научить шаблоны работать с базами данных - а помощь людям не может оставаться незамеченной: кто-то копеечкой благодарит, кто-то добрым словом, кто-то темку для заработка подбросит.
Если меня кто-то спросит, какой программой лучше всего автоматизировать какой-то процесс работы в интернете - я однозначно порекомендую Зеннопостер, так как сейчас не представляю, как можно зарабатывать в интернете без данной программы!
2.jpg

Когда речь идет об автоматизации - то в первую очередь приходится задать изначальные вводные данные, выставить требования к будущей системе и определить будущий результат работы.
В разрезе темы данной статьи под вводными данными мы можем подразумевать ключ API, ID канала, ID видео, временные токены, адрес сервера с установленой базой данных MySQL, логин к базе данных, пароль к базе данных, имя базы данных, таблицы базы данных, список значений которые будут получены в процессе работы и подобное...

Наша система автоматизации должна будет без использования браузера с помощью API YouTube (и/или POST/GET запросов) и программы Зеннопостер получать общедоступные данные о канале и видео (включая комментарии к видео) и сохранять полученные результаты работы в таблицы базы данных MySQL.

Удовлетворительным результатом будем считать решение, которое получив вводные данные, на выходе будет записывать результат в базу данных MySQL с возможностю многопоточной работы.
Впринципе уже имея эту информацию можно приступать к разработке шаблонов, котоыре будут выполнять данную работу. Но, я понимаю, что не все читатели данной статьи вплотную встречались с сбором информации на YouTube (а может вообще никогда не занимались парсингом информации с помощью Зеннопостера) - из-за чего прежде всего постараюсь ответить на несколько вопросов.

Кто владеет информацией, тот владеет миром - сказал когда-то Натан Ротшильд. А YouTube - это то место, в которое каждую минуту залетает более 400 часов видео!
Неужели среди такого количества различной информации с помощью автоматизации не получится извлечь хоть какую-то личную выгоду?

За несколько минут я набросал список идей, которые хотелось бы расширить. Так что если у вас есть идеи для чего можно еще использовать выборку общедоступной информации с YouTube – напишите, пожалуйста!

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

Просмотрев информацию о том, кто и где комментировал больше всего на канале – смогу, например, пройтись по этих каналах прокомментировать их ролики (обратить на свой канал внимание), либо смогу провести конкурс комментаторов на канале (так как четко смогу определить количество комментариев любым конкретным комментатором).

Собрав все ID своих видео, я смогу быстро скачать все превьюшки к роликам - потом посмотреть их, при желании переделать - и тем самым сделать канал более приветливым к новым зрителям.
Собрав всю информацию о роликах, я смогу структурировать информацию и, например, относительно этого создать несколько плейлистов с тематическими роликами.
Без проблем можно разбить все ролики на разделы на своем канале (плейлистами) - чтобы пользователям удобнее было находить необходимый материал.

Когда мы просто заходим на YouTube - мы не видим сразу, по каким ключевым словам нам выдаются результаты. Таким образом, мы просматриваем вагон разного мусора, прежде чем найдем что-то дельное.
Но, когда, к примеру, мы добавили в базу данных пару десятков тематичных каналов и собираем видео с них - то у нас есть возможность выбирать только ролики, например, с тегом ДЕНЬГИ и, например, с более чем 1000 лайков (и не более 100 дизлайков). Таким образом, просмотрев бегло свою базу данных можно находить как идеи для записи роликов (если тема актуальная - будут набирать просмотры), либо для заработка Зеннопостером.

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

Для продвижения разных серых каналов и серых блогов очень важно набирать большое количество комментариев, при чем, релевантных комментариев. Но где их брать? Правильно!
Собрав прежде базу данных, с YouTube, мы можем без проблем сделать выборку комментариев только с роликов с определенным нами тегом. Дальше можем отправить задание на рерайт с размещением в нужном месте (или поручить сам постинг Зеннопостеру).

Сбор комментариев на YouTube пригодится и тогда, когда нам нужно придумывать отзывы о товаре (выполняя прихоти заказчиков на фрилансе) - просто выборку с базы данных обратно берем по нужным тегам с условием длины не менее столько-то знаков.

А если нам на многих каналах попадаются одни и те же авторы комментариев это говорит о том, что это активные пользователи? Может, мы сможем, как-то обратить их внимание и превратить в подписчиков/клиентов?

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

В таком случае, возможно, было бы не плохо просто искать видео без описаний и тегов (благо у нас есть база данных с необходимой нам информацией) - и добавлять эти ролики себе в статьи - это повысит доверие поисковых систем к сайту/блогу.

Да и картинки уникальные получать не беда - ведь многие пользователи YouTube не заморачиваются рисованием превьюшек, и в качестве превью становится какой-то случайный кадр с видео. При желании на эту превьюшку можно просто добавить размытость и наложить крупный текст по центру - и уникальная картинка готова!

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

А потом с помощью Зеннопостера мы можем скачивать, например, субтитры и, конечно же, потом проверять их на уникальность. После того, как проверили и убедилить в уникальности можно отдавать на рерайт/корректировку и наполнять свои сайты (хотя, думаю, что даже без рерайта и корректировки данные тексты должны попадать в индекс поисковых систем).

Одно дело создавать автонаполняемые сайты, просто используя какие-то скрипты, которые парсят все что угодно, чисто с поиска YouTube. А уже совсем другое дело, когда мы собираем большое множество контента, вырезаем весь мусор, возможно синонимизируем описания и заголовки, и формируем уже более интересные сайтики (и да, никто не мешает еще и превьюшки маленько уникализировать Зеннопостером - уникальные картинки это хорошо для поисковых систем).

В сравнение с другими автонаполняемыми сайтами - данный подход позволит еще и комментировать ролики на наших сайтах - ведь материала в базе данных соберется вполне достаточно, чтобы оставлять только релевантные комментарии (благо Зеннопостер умеет постить хоть в WordPress, хоть в любой другой движок).

Для ведения групп главное контент. А где брать вирусный контент? Правильно! Пролайканные ролики или самые комментируемые ролики будут как раз в тему!
Тут вообще все предельно просто - создаем пачку групп типа "Котики улыбаются" и размещаем на автомате выборку по котикам. Создаем группу "Доберманы" - и у нас вагон как фоток (превьюшки к видео) и видео с Доберманами. И да, мы ведь можем с помощью Зеннопостера накладывать свои надписи на изображениях.

Сколько можно вести групп, к примеру, ВКонтакте с одного аккаунта? Но мы же не ищем легких путей, можем не брезговать и Фейсбуком и другими сетями.

И вот, мы определились, что нам необходимо собирать общедоступную информацию с YouTube. И конечно мы можем просто самостоятельно сидеть и в браузере вручную нажимать поочередно комбинации клавиш Ctrl+C и Ctrl+V. Но на сколько, времени хватит нашего терпения? А сколько информации мы сможем таким способом собрать?
Можно выделить три способа получения информации и не важно, с какого сервиса мы будем её собирать, при этом они имеют свои особенности, положительные и отрицательные стороны. Давайте рассмотрим их подробнее и на одном из них остановимся для сбора общедоступной информации с YouTube.

Когда мы просто открываем браузер, открываем страничку, на которой находится необходимая нам информация, выделяем фрагмент, потом копируем и вставляем, например, в блокнот - это и будет сбор информации в браузере. Этот процесс можно автоматизировать каким-либо автокликером (например, Tasker или АвтоКликЭкстрим) - но в таком случае мы уже не сможем пользоваться компьютером, так как автокликер просто заберет у нас мышку и будет выполнять поставленную задачу.

Чтобы как-то обеспечить многопоточность я когда-то просто устанавливал несколько виртуальных машин, и на каждой запускал одну копию (браузер + автокликер). Вот только такое решение по автоматизации сложно было переносить, потребляло много ресурсов - из-за чего страдала и скорость работы.

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

И когда я уже начал работать программой Зеннопостер, то большинство проблем пропало сразу - многопоточность поддерживается с коробки, возможность записывать информацию с многих потоков в один файл. Обработка ошибок и возможность наглядно проектировать логику шаблона. При этом есть возможность отключения отображения браузера (что экономит ресурсы) и отключения всех ненужных фишек браузера (загрузку стилей, флеш, аудио и видео).

Так как при сборе общедоступной информации с YouTube важна скорость получения данных и использование браузера не обязательно (нет каптчи и других защит) - то я буду писать шаблоны, которые не используют браузер.

Браузер взаимодействует с сайтами посредством нескольких типов запросов, в частности POST и GET (есть и другие...). Когда мы открываем какую-то страничку - браузер отправляет серию запросов, загружая нужный нам контент, потом разные стили, скрипты, формы, рекламу, аналитику.

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

Для сбора информации с помощью POST/GET запросов можно использовать разные специализированные парсеры, например Ccontent Downloader, А-Парсер, а можно к примеру с помощью скриптов VBA, JS, PHP, C# и даже можно напрямую парсить информацию в Google Table используя скрипты для данных таблиц. Но, тут нужно уже обладать знаниями программирования.

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

Большие сайты, такие как YouTube, Vk, FB и подобные предоставляют инструменты для разработчиков приложений - API. Это практически те же самые POST/GET запросы, только отправляются по четко определенным правилам.
На каждом сайте, который предоставляет API, есть техническая документация, в которой рассказывается о том, как использовать данные инструменты в своих приложениях (а свои приложения - это могут быть как свои сайты, мобильные приложения или даже шаблоны Зеннопостера).

Удобность использования инструментов для разработчиков в сравнении с обычными запросами в том, что в обычном запросе мы можем получить только то, что обычно отображается в браузере. А через API - мы можем получить, например, выборку сразу из 50 страниц всего одним запросом без лишнего мусора (в виде оформления).
Для работы с API необходимо получить ключ доступа. Этим ключем определяется, что нам можно делать, что нельзя. Также для каждого ключа определяется индивидуальное количество запросов в сутки, в час, в минуту - так называймая квота.

Как получить API ключ YouTube можно посмотреть здесь (видео). Именно этот ключик мы будем использовать дальше для наших шаблонов. Мне было достаточно одного ключа - но, в зависимости от целей можно получить несколько.
Хочу также отметить, что бывает такое, что часть информации мы не можем (не предусмотрено) получить с помощью API (на YouTube это количество зрителей на онлайн трансляции или, например, видео в разделе "В тренде"). В таком случае можно просто воспользоваться обычными POST/GET запросами.

В документации YouTube API v3 говорится о том, что мы можем получить общедоступную информацию (свойство) о любом ресурсе (под ресурсом подразумеваются каналы, видео, плейлисты) отправив обычный GET запрос, в котором будет указан ID ресурса (например, ID канала или видео), API KEY и группа свойств (список полей) которые желаем получить.
Пример из документации (основная ссылка:
HTML:
https://www.googleapis.com/youtube/v3/videos?id=ID_VIDEO&key=YOUR_API_KEY )
&part=snippet,contentDetails,statistics,status
&part=snippet,statistics
&part=snippet,statistics&fields=items(id,snippet,statistics)
&fields=items(id,snippet(channelId,title,categoryId),statistics)&part=snippet,statistics
Данным запросом мы и будем пользоваться в разных вариациях для получения общедоступных данных с YouTube.

Когда я пишу шаблон для Зеннопостера, то мне важно понимать что я буду использовать в процессе работы. Я точно знаю, что буду писать парсер в Project Maker, в основном буду использовать пост/гет запросы и API v3 – значит, понадобится ключик YouTube API v3. А вот с сохранением результатов необходимо определиться. У меня есть несколько вариантов, которые я могу без проблем использовать:
  • Шаблон Зеннопостер + txt файлы
  • Шаблон Зеннопостер + csv файлы
  • Шаблон Зеннопостер + excel файлы
Текстовые файлы и таблицы csv / excel могут использоваться для личных целей (быстрого просмотра, анализа), либо например дальнейшего импорта в программу Зеброид для генерации сайтов, дальнейшей их перелинковки и заливки на хостинги.
  • Шаблон Зеннопостер + html файлы
  • Шаблон Зеннопостер + pdf файлы
  • Шаблон Зеннопостер + jpg файлы
html + css могут использоваться для создания сайтов, генерации изображений и документов pdf - с последующим размещением на гугл диск и вбросом в индекс поисковых систем (говорят, что очень не плохо там держутся).
jpg могут использоваться для создания видео например с помощью кодека ffmpeg с подальшей заливкой на YouTube.
  • Шаблон Зеннопостер + база данных MySQL
Сохранение в базу данных позволяет быстро получать всевозможные выборки данных для дальнейшей обработки (создания тех же документов, картинок, видео) так и напрямую подключаться к сайтам (создания автонаполняемых сайтов).
Так как информации о работе Зеннопостером в комплексе с базами данных столько, что на пальцах можно подсчитать материалы - то думаю, будет полезно описать работу шаблонов именно с базой данных.

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

Думаю это не особо правильная стратегия, так как владельцы каналов миллионников очень редко оставляют комментарии и таким образом они могут просто не попасть в нашу базу данных - тут нужно выбрать какую-то другую стратегию пополнения базы новыми каналами.
Второй источник пополнения базы данных новыми каналами – это, к примеру, парсинг сервиса socialblade.com - там уже есть готовая информация, которую нужно только собрать, а уже отработать по цепочке описанной выше. С другой стороны рассчитывать только на данный сервис нельзя - так как в таком случае можно отбросить львиную долю маленьких каналов.

Третья стратегия пополнения базы данных новыми каналами - это создание шаблона, который каждых несколько минут отправлял бы запрос на страничку "В Тренде" с разных IP (выдача с разных стран отличается) и получал бы оттуда список каналов, после чего добавлял бы их в базу и дальше эти каналы обрабатывались бы по цепочке.
Можно придумать какие-то другие схемы - и я уверен, что вам это получится лучше, чем мне! А я выбрал для себя первую и пока не расширял количество шаблонов - нет пока экстерной необходимости в этом.
3.jpg

Когда мы определились с способом сбора общедоступной информации с YouTube и наш выбор остановился на работе с API - то как раз пришло время подумать над тем, как мы будем осуществлять данную работу.

Прежде всего, нам нужно закопаться в техническую документацию YouTube для разработчиков и найти там те запросы, которые будут выдавать нам необходимый результат.

После чего полученный результат необходимо будет разобрать регулярными выражениями по переменных (либо сразу в списки и таблицы).

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

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

Не замысловатый план действий, не так ли? И все же предлагаю остановиться на данных пунктах подробнее.

Для работы с общедоступными данными YouTube через API v3 мы должны прежде всего получить ключ (видеоинструкция получения API KEY YouTube
) и сохранить его себе в переменную, после чего подставлять переменную в запросах, которые его требуют. Хранить ключ я буду в переменной {-Variable.api_key-}.

Также нам понадобится идентификатор ресурса (например, ИД канала, ИД плейлиста или ИД видео). Например если мы работаем только с одним каналом - то ИД канала мы можем задать в входящих настройках. ИД плейлиста мы получим в результате получения информации о канале, а уже ИД видео получим в результате выполнения запроса на получение списка видео с плейлиста.

И так, для первого запроса, который будет возвращать информацию о канале, ИД канала я буду хратить в переменной: {-Variable.id_channel-}, а API KEY YouTube в переменной: {-Variable.api_key-}.

Отправив обычный GET запрос, я смогу получить необходимую мне информацию о канале и сохранить результат, например в переменную {-Variable.get-}.

Кстати, при желании я могу таким образом получить информацию о нескольких каналах, указав ИД каналов в запросе через запятую.

Запрос
Код:
https://www.googleapis.com/youtube/v3/channels?part=id,snippet,statistics,contentDetails,brandingSettings,contentOwnerDetails&id={-Variable.id_channel-}&key={-Variable.api_key-}
После получения информации о выбранном канале среди разных прочих параметров есть такой:
Код:
"uploads": "UUGVQdcoALJ_YoNOy_TtJWMQ"
В нем хранятся все загруженные на канал видео. Именно данный идентификатор мы и будем использовать в текущем запросе и хранить его будем в переменной {-Variable.uploads-}.

Вот только есть каналы на которых 10 видео, а есть у которых 10 000 видео. Так вот, если в плейлисте находится много роликов, то при запросе мы получим только первую страничку с роликами (максимально 50 роликов за раз). Но результат выполнения запроса будет содержать еще и токен на вторую страничку с роликами. Таким образом первый запрос мы будем отправлять без токена, а если после выполнения запроса токен обнаружен - будем пытаться получить следующую страничку с видео. Токен сохраним в переменную {-Variable.token_list_video-}.

Собственно пришли мы к тому, что у нас будет два разных запроса, которые будут возвращать примерно одинаковый результат (за исключением самих роликов).

Запрос с токеном
Код:
https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId={-Variable.uploads-}&maxResults=50&key={-Variable.api_key-}&pageToken={-Variable.token_list_video-}
Запрос без токена
Код:
https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&playlistId={-Variable.uploads-}&maxResults=50&key={-Variable.api_key-}
И вот, после получения списка роликов мы можем встретить параметр "videoId": "4AQ9UamPN6E" который отвечает за ИД видео. Имея данный параметр мы уже можем обратиться к API Youtube за возвратом дополнительной информации о ролике. Хранить данный параметр я буду в переменной {-Variable.id_video_table-}. И в результате выполнения запроса буду получать подробную информацию о ролике.

Запрос
Код:
https://www.googleapis.com/youtube/v3/videos?id={-Variable.id_video_table-}&part=id,snippet,status,statistics&key={-Variable.api_key-}
И последний запрос который нам понадобится - это запрос, который будет получать комментарии к видео. Для получения комментариев будет использоваться тот же ИД видео, который использовался в предыдущем запросе. Вы можете спросить конечно, почему мы эти данные не собрали сразу? Все просто - есть ролики у которых по 100 000 комментариев. Если зациклить это в одном шаблоне - то мы будем собирать только комментарии - а нам ведь базу данных нужно наполнять более-менее равномерно.

Так как комментарии мы также будем получать по несколько штук одновременно, то обратно будем использовать два запроса - один с токеном, другой - без токена. Это позволит естественно ускорить процесс парсинга информации.

Запрос без токена
Код:
https://www.googleapis.com/youtube/v3/commentThreads?part=snippet,replies&videoId={-Variable.id_video_comment-}&key={-Variable.api_key-}&maxResults=100&textFormat=plainText
Запрос с токеном
Код:
https://www.googleapis.com/youtube/v3/commentThreads?part=snippet,replies&videoId={-Variable.id_video_comment-}&key={-Variable.api_key-}&maxResults=100&textFormat=plainText&pageToken={-Variable.token_list_comment-}
В результате выполнения наших GET запросов к API YouTube мы получим масив данных о канале, плейлисте, видео, комментариях в формате JSON. Зеннопостер конечно умеет работать с данными JSON, вот только мне удобнее работать регулярными выражениями - но уверен, что при необходимости вы сможете переписать себе решение с использованием этого нового инструмента в Зеннопостере.

Так как данных будет много, то использование стандартных кубиков приведет к увеличению шаблона (как следствие - сложнее разобраться, что и как работает и где допустил ошибку). Из-за чего я решил использовать сниппеты и общий код.

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

Данный фрагмент кода принимает на вход строку. Проверяет пустая ли она и если да, то заменяет нулевым значением и удаляет кавычки.
Код:
public static string Ziro (string x) {
  if(string.IsNullOrEmpty(x))  x = "0";
  x=x.Replace("\'","").Replace("\"","").Trim();
  return x.ToString();
}
Данный фрагмент кода принимает две строки (в одной текст в котором будем искать что-либо, во второй - регулярное выражение) и на выходе возвращает либо ноль (если ничего не найдено) либо результат поиска по данному регулярному выражению.
Код:
public static string re (string text, string reg) {
  var rez = new System.Text.RegularExpressions.Regex(@reg);
  var rezult= rez.Match(text);
  if (rezult.Success)  {
     return rezult.Value.Trim();
     }
  else {
     return "0";
  }
}

Чтобы работать в сниппете с данными необходимо создать переменные, в которых будут храниться регулярные выражения, которые будут использованы для извлечения необходимых данных, да и переменные в которых будет храниться результат. Приведу пример на первом шаблоне (в остальных все сделано практически по аналогии):
Код:
// Забрасываю результат нашего запроса в переменную
var parse = project.Variables["get"].Value;

// Создаю переменные, которые содержат регулярные выражения
string re_json = @"""kind""[\w\W]*?000Z""\s+}";
string re_featuredChannelsUrls = @"(?<=""featuredChannelsUrls"": "").*?(?="")";
string re_id = @"(?<=""id"": "").*(?="")";
string re_title = @"(?<=""title"": "").*(?="")";
string re_description = @"(?<=""description"": "").*(?="")";
string re_customUrl = @"(?<=""customUrl"": "").*(?="")";
string re_publishedAt = @"(?<=""publishedAt"": "").*(?="")";
string re_url = @"(?<=""url"": "").*(?="")";
string re_uploads = @"(?<=""uploads"": "").*(?="")";
string re_likes = @"(?<=""likes"": "").*(?="")";
string re_favorites = @"(?<=""favorites"": "").*(?="")";
string re_viewCount = @"(?<=""viewCount"": "").*(?="")";
string re_commentCount = @"(?<=""commentCount"": "").*(?="")";
string re_subscriberCount = @"(?<=""subscriberCount"": "").*(?="")";
string re_hiddenSubscriberCount = @"(?<=""hiddenSubscriberCount"": "").*(?="")";
string re_videoCount = @"(?<=""videoCount"": "").*(?="")";
string re_showRelatedChannels = @"(?<=""showRelatedChannels"": "").*(?="")";
string re_featuredChannelsTitle = @"(?<=""featuredChannelsTitle"": "").*(?="")";
string re_Count = @"(?<=""Count"": "").*(?="")";
string re_unsubscribedTrailer = @"(?<=""unsubscribedTrailer"": "").*(?="")";
string re_profileColor = @"(?<=""profileColor"": "").*(?="")";
string re_bannerTvHighImageUrl = @"(?<=""bannerTvHighImageUrl"": "").*(?="")";

Таким образом, все необходимые регулярные выражения находятся в одном месте, и в случае необходимости можно быстро изменить их. Чтобы понимать, что в данной переменной хранится регулярное выражение, я в названии переменной использовал приставку re_.
Код:
// Создаю переменные, которые должны хранить результат поска по регулярному выражению
string id = String.Empty;
string title = String.Empty;
string description = String.Empty;
string customUrl = String.Empty;
string publishedAt = String.Empty;
string url = String.Empty;
string uploads = String.Empty;
string likes = String.Empty;
string favorites = String.Empty;
string viewCount = String.Empty;
string commentCount = String.Empty;
string subscriberCount = String.Empty;
string hiddenSubscriberCount = String.Empty;
string videoCount = String.Empty;
string showRelatedChannels = String.Empty;
string featuredChannelsTitle = String.Empty;
string Count = String.Empty;
string unsubscribedTrailer = String.Empty;
string profileColor = String.Empty;
string bannerTvHighImageUrl = String.Empty;

Дальше осталось получить результат в созданные переменные:
Переменной id присваиваю результат вызова метода re который создал в общем коде, в который передаю содержимое переменной результата запроса к API и регулярное выражение. Метод вернет готовый результат, обрезав пробелы вначале и вконце строки и если ничего не обнаружит - вернет ноль.
Код:
id = CommonCode.re(parse, re_id);
Аналогичным образом получаю результат для всех остальных необходимых мне переменных.
Код:
title = CommonCode.re(parse, re_title);
description = CommonCode.re(parse, re_description);
customUrl = CommonCode.re(parse, re_customUrl);
publishedAt = CommonCode.re(parse, re_publishedAt);
url = CommonCode.re(parse, re_url);
uploads = CommonCode.re(parse, re_uploads);
likes = CommonCode.re(parse, re_likes);
favorites = CommonCode.re(parse, re_favorites);
viewCount = CommonCode.re(parse, re_viewCount);
commentCount = CommonCode.re(parse, re_commentCount);
subscriberCount = CommonCode.re(parse, re_subscriberCount);
hiddenSubscriberCount = CommonCode.re(parse, re_hiddenSubscriberCount);
videoCount = CommonCode.re(parse, re_videoCount);
showRelatedChannels = CommonCode.re(parse, re_showRelatedChannels);
featuredChannelsTitle = CommonCode.re(parse, re_featuredChannelsTitle);
Count = CommonCode.re(parse, re_Count);
unsubscribedTrailer = CommonCode.re(parse, re_unsubscribedTrailer);
profileColor = CommonCode.re(parse, re_profileColor);
bannerTvHighImageUrl = CommonCode.re(parse, re_bannerTvHighImageUrl);
Так как список подобных каналов это несколько значений одного и того же поля ИД канала - то я решил его забросить сразу в список для дальнейшего добавления в базу данных.
Код:
// Беру список подобных каналов если такие есть

var regex = new Regex(re_featuredChannelsUrls);
var zp_list = project.Lists["Каналы"];
regex.Matches(parse).Cast<Match>().ToList().ForEach(m=>zp_list.Add(m.Value));

Для добавления данных в базу я буду использовать запрос
SQL:
INSERT INTO table(field,field..field)
VALUES ("val", "val", ..., "val")
ON DUPLICATE KEY UPDATE val=VALUES(val),
val=VALUES(val),..,val=VALUES(val)
Данный запрос позволяет добавлять в базу данные, при чем обнаруживая дубликат база данных автоматически обновит все значения полей новыми данными (что позволит не дублировать данные в базе).

Собственно формирование запроса будет сводиться к тому, чтобы сформировать строку с значениями в виде: ("val", "val", ..., "val") - это я и сделаю сразу же после разбора результата по переменных.
Код:
string z = "\", \"";
project.Variables["query_channel_info"].Value = "(\""
  +id + z
  +title + z
  +description + z
  +customUrl + z
  +publishedAt+ z
  +url + z
  +uploads + z
  +likes + z
  +favorites + z
  +viewCount + z
  +commentCount + z
  +subscriberCount + z
  +hiddenSubscriberCount + z
  +videoCount + z
  +showRelatedChannels + z
  +featuredChannelsTitle + z
  +Count + z
  +unsubscribedTrailer + z
  +profileColor + z
  +bannerTvHighImageUrl + "\")";
Конечно можно было сделать по другому - прежде получить ИД канала с базы - и если получили - тогда отправлять запрос на обновление данных, а если ничего не получили - тогда добавлять. Но, использование данного запроса мне показалось более корректным (хотя, я могу ошибаться).

После подготовки данных для добавления в базу данных необходимо сформировать сам запрос, который будет отправлен для добавления данных. Как я уже выше написал - использоваться будет запрос:
SQL:
INSERT INTO... ON DUPLICATE KEY UPDATE
Но, кто не работал с базой данных возможно ничего не понял и не представляет как будет выглядеть данный запрос. Специально для этого копирую содержимое запроса, который использую я в одном шаблоне (по аналогии и в других только поля таблицы базы данных отличаются).
SQL:
INSERT INTO channel (channel.id,
channel.title,
channel.description,
channel.customUrl,
channel.publishedAt,
channel.thumbnails_high_url,
channel.relatedPlaylists_uploads,
channel.relatedPlaylists_likes,
channel.0x300relatedPlaylists.favorites0x300,
channel.viewCount,
channel.commentCount,
channel.subscriberCount,
channel.hiddenSubscriberCount,
channel.videoCount,
channel.showRelatedChannels,
channel.featuredChannelsTitle,
channel.featuredChannelsUrls_Count,
channel.unsubscribedTrailer,
channel.profileColor,
channel.bannerTvHighImageUrl)
VALUES {- Variable.query_channel_info -}
ON DUPLICATE KEY UPDATE
channel.title=VALUES(channel.title),
channel.description=VALUES(channel.description),
channel.customUrl=VALUES(channel.customUrl),
channel.publishedAt=VALUES(channel.publishedAt),
channel.thumbnails_high_url=VALUES(channel.thumbnails_high_url),
channel.relatedPlaylists_uploads=VALUES(channel.relatedPlaylists_uploads),
channel.relatedPlaylists_likes=VALUES(channel.relatedPlaylists_likes),
channel.0x300relatedPlaylists.favorites0x300=VALUES(channel.0x300relatedPlaylists.favorites0x300),
channel.viewCount=VALUES(channel.viewCount),
channel.commentCount=VALUES(channel.commentCount),
channel.subscriberCount=VALUES(channel.subscriberCount),
channel.hiddenSubscriberCount=VALUES(channel.hiddenSubscriberCount),
channel.videoCount=VALUES(channel.videoCount),
channel.showRelatedChannels=VALUES(channel.showRelatedChannels),
channel.featuredChannelsTitle=VALUES(channel.featuredChannelsTitle),
channel.featuredChannelsUrls_Count=VALUES(channel.featuredChannelsUrls_Count),
channel.unsubscribedTrailer =VALUES(channel.unsubscribedTrailer),
channel.profileColor =VALUES(channel.profileColor),
channel.bannerTvHighImageUrl=VALUES(channel.bannerTvHighImageUrl);
В данном случае в переменной {- Variable.query_channel_info -} будут находиться данные сформированные зарание в ввиде ("val", "val", ..., "val").
Так как база данных нам ничего возвращать не должна - то установим тип запроса в экшине Без ответа - и после выполнения запроса в переменную получим количество добавленных строк в базу данных (при желании можно будет относительно этого каким-то образом строить логику).
Если мы научились собирать информацию, но не определились, куда мы её будем сохранять (и будем ли сохранять вообще) - то это говорит о том, что еще не вся миссия выполнена.

Есть несколько вариантов, которые можно использовать для сохранения данных - это таблицы, списки, облако и базы данных. Нет, я не говорю что мы не можем формировать html документы и сразу же заливать по FTP на хостинги либо сразу через API BLOGGER на блоги или как уже описывали другие участники форума на фрихосты и блоги WordPress - это все можно и даже нужно по необходимости.

Только обычно получается так - собрали мы информацию. Провели анализ этих данных, сделали для себя выборку только необходимых данных - все остальное удалили и продолжили работать уже с узконаправленным количеством материала.

Впринципе я для себя определился, что буду работать с базой данных MySQL - но описание возможных вариантов я все же предоставлю (мало ли, вдруг кому-то пригодится).
Сохранение полученных данных в таблицу возможно очень даже просто - так как в переменных у нас уже есть данные - то мы можем допустим сформировать строку с разделителями, после чего добавить эту строку в таблицу хоть стандартным экшином, что и сниппетом, например таким:
Код:
//таблица, в которую сохранять результат
var table= project.Tables["table"];
//var строка, подготовленная для добавления в таблицу
table.AddRow(var);
Возможно такой вариант при работе с одним или десятком каналов будет более предпочтительным, но при большом количестве данных работать с таблицами не очень удобно.

Сохранение полученных данных в список возможно очень даже просто, как и с сохранением в таблицу - так как в переменных у нас уже есть данные - то мы можем, допустим, сформировать строку с разделителями, после чего добавить эту строку в список хоть стандартным экшином, что и сниппетом, например таким:

Код:
//список, в который будем сохранять результат
var list = project.project.Lists["list"];
list.Add(var); //var строка, подготовленная для добавления в список
Возможно, такой вариант при работе с одним или десятком каналов будет более предпочтительным, аналогично, как и с сохранением данных в обычную таблицу, но при большом количестве данных работать со списками не очень удобно.

Можно не доверять локальным файлам, и отправлять запросами данные например в таблицы Google. Естественно, что это достаточно удобный вариант, так как на компьютере тогда ничего не сохраняется - результат в любой момент можно посмотреть с любого устройства. Я когда-то именно так и делал. Как сохранять данные в таблицы запросами можно посмотреть в видео:
... и адаптировать под свои конкретные нужды.

Вот только проблемой таких таблицы (для меня) является сам факт, что хранить в них можно только 2 000 000 ячеек. Это в свою очередь говорит что при парсинге данных нам придется очень часто менять эти таблицы. Да, как вариант просто хранить в каждой отдельной таблице информацию об одном канале (но в таком случае если на канале 100 000 видео всеравно придется делать несколько таблиц).

Наиболее предпочтительным для сохранения результата я выбрал базу данных MySQL ( http://zennolab.com/discussion/threads/primer-proektirovanija-bazy-dannyx-mysql-dlja-raboty-s-shablonami-zennopostera.35715/ ). Дело в том, что с одной стороны количество данных, которые будут собираться со временем, будет просто огромным (40ГБ+) и никакие текстовые файлы и таблицы Excel с этим не справлятся.

С другой стороны база данных у меня установлена на выделенном сервере, и ничего не мешает взять её за основу создания, например миллиона автонаполняемых сайтов с видео (каждому сайту, к примеру, один канал на YouTube). При этом с базы данных очень просто получить выборку данных по различным параметрам (например, получить только ролики пользователей, у которых меньше 1000 подписчиков, но видео с количеством просмотров более 100 000 и при этом чтобы количество лайков на видео было не меньше 10 000 и дизлайков не больше 1000), а вот такую выборку сделать из списков/таблиц я считаю, будет более проблематично.


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

Так вот сейчас я могу сказать, что для создания базы данных для хранения данных которые будут собирать мои шаблоны с YouTube используя APIv3 мне понадобилось знать всего лишь где читать справку по MySQL.

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

Когда я принял решение собирать данные на YouTube, я знал что мне необходимо знать, кто ведет канал, сколько у него роликов, сколько просмотров и когда зарегистрирован канал. Но, когда я уже обратился через API к YouTube - то увидел, что он предоставляет по каналу дополнительные данные, которые я также решил сохранить. Итого - сам канал оброс огромным количеством параметров (кто знает, вдруг в будущем пригодятся).

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

Дальше я решил собрать информацию о самих видео. И когда уже обратился к YouTube, то увидел огромное количество информации - естественно я решил её сохранить. В частном случае это теги, которые автор видео указывает, чтобы его ролик смогли найти зрители. Так как роликов в интернете много, то я предположил, что в некоторых роликах теги будут дублироваться. А значит - сохранять копии тегов было бы не правильно.

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

Собственно что я подразумеваю под служебными полями? Допустим, работает у нас шаблон. Если он работает без базы данных, то он берет из списка первую строчку, удаляет её и сохраняе в конец списка. Так обеспечивается многопоточность.

Так вот для работы с базой данных данный момент я реализовал таким способом - добавил поле STATUS, в котором хранится значение занятости строчки (0,1,2,3...). И добавил поле TIMESTAMP в котором хранится дата и время последнего изменения данной строки в базе данных.

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

А так как при изменении статуса временная метка изменится - то наша строчка улетит в нашей сортировке в конец таблицы (а мы с базы всегда будем брать именно первую строчку). Так потоки работают и не пересекаются (пересекаются, конечно, если поток отрабатывает очень быстро - но они у меня работают без браузера - а значит, места занимают мало и мне при необходимости не сложно добавить 2-3 секунды принудительной паузы, чтобы поток зря не долбился в базу данных запросами).

Вот собственно и все служебные поля, которые мне нужны для создания работоспособных шаблонов. Но, когда я уже начал работать с API, и встретил токены страничек, то пришлось добавить поле, которое хранило бы данный токен для каждого отдельного канала или видео (к примеру, чтобы не зацикливать шаблон при парсинге 100 000 комментариев к видео).

Это позволило шаблону быстрее заканчивать работу - а другой (следующий) поток мог без проблем продолжить скачивать комментарии к этому видео.

Когда я создаю базу данных MySQL, которой буду пользоваться самостоятельно, то просто в программе Navicat добавляю необходимые мне таблицы и поля. Ничего сложного - как в Excel или Access.

Просто выписываю себе все переменные, содержимое которых хочу хранить в базе данных, выписываю, какие там будут данные (строки, цифры, даты) и количество символов при необходимости, какие будут поля иметь значения по умолчанию, если не будет никаких данных передано в запросе.

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

И тут конечно есть два варианта. Первый вариант - просто создать копию своей базы данных и предоставить файл, который человеку придется импортировать в свою базу данных. Но и тут, бывает, приходится потом тратить время на объяснения что да как сделать.

И я пришел к выводу, что куда правильней будет просто создать шаблон, в котором будет этих несколько запросов, которые будут выполняться один раз по очереди - создадут необходимые таблички.

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

Данные запросы мы сохраняем в переменные и добавляем столько экшинов по работе с базой данных, сколько у нас есть таблиц. Во входящих настройках, конечно же, добавляем возможность задать данные для доступа к базе данных (сервер, базу, логин, пароль) - это позволит предоставлять данный шаблон так сказать в "коробочном" решении - а пользователю не придется открывать ПроджектМейкер, не придется устанавливать даже Навикат. Удобно...

Для работы с базой данных в основном используются запросы SELECT, INSERT, UPDATE и сейчас я начал использовать и DELETE (раньше как-то не приходилось его использовать). Естественно, что данные запросы не сложные - вполне себе обычные запросы... Но мне, когда я разбирался с тем, как работать с базами данных, нехватало информации о том, как конкретно должны выглядеть запросы к базе данных, для работы с ней шаблонами Зеннопостера. Везде примеры в основном на PHP с учитыванием особенности языка, например формирование запроса в цикле, вывод строк в цикле и так далее.

Так что - отталкиваясь от того, чего мне нехватало, я предоставлю запросы полностью, чтобы их при желании можно было использовать в качестве примера и понимать, зачем они используются.

Впринципе, вся цепочка шаблонов работает со статусами разных таблиц. Например, статус канала проходит изменения от 0 до 9 пока не будет выполнена вся работа. Мне показался удобным такой контроль работы на каждом шаге. В случае, если где-то что-то подвисло, не докачалось - то каналы будут иметь промежуточные статусы занятости (например: 1, 3, 5) - и их можно одним запросом освободить после чего шаблоны их подхватят и выполнят работу полностью как было запланировано.

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

Первый SQL запрос, который будет использоваться - это получение ИД канала, информацию о котором мы желаем получить. У меня все каналы, которые добавляются в базу данных, получают статус 0 - итого - я собираю информацию обо всех каналах. При желании можно, например, всем каналам, которые добавляются присвоить какой-то другой статус, а уже по определенным параметрам менять этот статус в значение ноль - после чего шаблон будет подхватывать его.

Код:
SELECT channel.id FROM channel WHERE channel.0x300status0x300 = 0 LIMIT 1
Дальше мне необходимо изменить статус канала с 0 на 1, чтобы никакой другой поток Зеннопостера случайно не подхватил данную строчку (чтобы несколько потоков не выполняло одну и ту же работу). Для этого будет использоваться запрос, который меняет значение в поле статус на 1 при условии, что ИД канала соответствует значению, которое мы получили предыдущим запросом и в поле статус не содержится значение 1.

Код:
UPDATE channel SET channel.0x300status0x300 = 1 WHERE channel.id = "{-Variable.id_channel-}" AND channel.0x300status0x300 <> 1 LIMIT 1
Если после выполнения первого запроса мы ничего не получили - значит можно выполнить удаление пустых строчек (мало ли где-то не уследили - не хотел я вводить дополнительную проверку во всех шаблонах). Естественно - данный шаблон удалит все пустые строчки в указанной нами таблице.

Код:
DELETE FROM channel WHERE channel.id="";
И вот, после того как мы уже получили данные с YouTube то можно смело добавлять данны в базу. Для этого используется следующий запрос:

Код:
INSERT into channel( channel.id, channel.title, channel.description, channel.customUrl, channel.publishedAt, channel.thumbnails_high_url, channel.relatedPlaylists_uploads, channel.relatedPlaylists_likes, channel.0x300relatedPlaylists.favorites0x300, channel.viewCount, channel.commentCount, channel.subscriberCount, channel.hiddenSubscriberCount, channel.videoCount, channel.showRelatedChannels, channel.featuredChannelsTitle, channel.featuredChannelsUrls_Count, channel.unsubscribedTrailer, channel.profileColor, channel.bannerTvHighImageUrl) VALUES {-Variable.query_channel_info-} ON DUPLICATE KEY UPDATE channel.title=VALUES(channel.title), channel.description=VALUES(channel.description), channel.customUrl=VALUES(channel.customUrl), channel.publishedAt=VALUES(channel.publishedAt), channel.thumbnails_high_url=VALUES(channel.thumbnails_high_url), channel.relatedPlaylists_uploads=VALUES(channel.relatedPlaylists_uploads), channel.relatedPlaylists_likes=VALUES(channel.relatedPlaylists_likes), channel.0x300relatedPlaylists.favorites0x300=VALUES(channel.0x300relatedPlaylists.favorites0x300), channel.viewCount=VALUES(channel.viewCount), channel.commentCount=VALUES(channel.commentCount), channel.subscriberCount=VALUES(channel.subscriberCount), channel.hiddenSubscriberCount=VALUES(channel.hiddenSubscriberCount), channel.videoCount=VALUES(channel.videoCount), channel.showRelatedChannels=VALUES(channel.showRelatedChannels), channel.featuredChannelsTitle=VALUES(channel.featuredChannelsTitle), channel.featuredChannelsUrls_Count=VALUES(channel.featuredChannelsUrls_Count), channel.unsubscribedTrailer=VALUES(channel.unsubscribedTrailer), channel.profileColor=VALUES(channel.profileColor), channel.bannerTvHighImageUrl=VALUES(channel.bannerTvHighImageUrl);
Естественно, что после того, как мы закончили работать с данным каналом (получили необходимые данные) то можем изменить статус в значение 2 - это даст право следующим шаблонам продолжать собирать информацию о видео на данном канале.

Код:
UPDATE channel SET channel.0x300status0x300 = 2 WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1

Как и в предыдущем шаблоне - мы будем получать ИД канала, со значением статуса 2, но при этом убедимся, что количество видео на канале больше 0 (нет смысла скачивать видео на канале, на котором нет видео).

Код:
SELECT channel.id FROM channel WHERE channel.0x300status0x300 = 2 AND channel.videoCount > 0 LIMIT 1
Так вот, если мы что-либо получили - значит, можем изменить статус канала с 2 на 3, тем самим, обозначив, что мы в текущий момент уже работаем с данным каналом, и что в данный момент другой поток уже не может его брать в обработку.

Код:
UPDATE channel SET channel.0x300status0x300 = 3 WHERE channel.id = "{-Variable.id_channel-}" AND channel.0x300status0x300 <> 3 LIMIT 1
Как и в предыдущем шаблоне если после выполнения первого запроса мы ничего не получили в ответ от базы данных - попытаемся удалить пустые строки.

Код:
DELETE FROM channel WHERE channel.id="";
Дальше мы можем получить значение количества видео на канале, которое храниться в табличке со списком каналов. Делается это обычным запросом, который вернет нам необходимое значение.

Код:
SELECT channel.videoCount FROM channel WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1
И получить количество видео, уже добавленных в базу данных с данного канала - для этого будем использовать функцию Count, которая подсчитает количество строк в базе данных по указанным нами параметрам.

Код:
SELECT Count(video.id_video) FROM video WHERE video.id_channel = "{-Variable.id_channel-}" LIMIT 1
После того, как мы определились с тем, что видео в базе данных недостаточно, и нам необходимо докачать новые ролики - мы можем получить с базы данных плейлист, в котором хранятся все загруженные ролики на канале и токен странички (возможно уже другой поток скачал первых парочку роликов и сохранил для нас токен).

Код:
SELECT channel.relatedPlaylists_uploads, channel.token_list_video FROM channel WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1
Дальше идет изменение статусов относительно условий - если видео скачано уже, и нам необходимо прекратить работать с каналом - один статус, если же необходимо скачивать видео, но токен обнаружен - то наверно необходимо обнулить токен (чтобы другой поток не мог подхватить его и выполнял бесполезную работу).

Код:
UPDATE channel SET channel.0x300status0x300 = 5, channel.token_list_video = "0" WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1
UPDATE channel SET channel.0x300status0x300 = 4 WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1
И вот, когда мы уже скачали список видео - то мы можем его добавить в базу данных - запрос будет иметь следующий вид.

Код:
INSERT INTO video (video.id_video, video.id_channel, video.title, video.data_greate, video.discription) VALUES {-Variable.query_video_list-} ON DUPLICATE KEY UPDATE 0x300timestamp0x300=now()
При этом, видим, что если появляются дубли - то обновляется временная метка. В данном случае не принципиально важно обновлять другие поля - так как статистика не содержится в наших данных - статистику будет собирать следующий шаблон.

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

Код:
UPDATE channel SET channel.0x300status0x300 = 2, channel.token_list_video = "{-Variable.token_list_video-}"  WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1
Но когда токен не обнаружен - это значит, что мы уже скачали все видео - а значит, можем установить статус канала в значение, при котором с ним уже сможет работать другой шаблон. Не забываем обнулить токен.

Код:
UPDATE channel SET channel.0x300status0x300 = 5, channel.token_list_video = "0" WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1

Как и в предыдущих шаблонах мы видим, что обратно получаем ИД канала, с которым желаем работать, но в этот раз получаем канал с статусом 5 и количеством видео больше нуля.

Код:
SELECT channel.id FROM channel WHERE channel.0x300status0x300 = 5 AND channel.videoCount > 0 LIMIT 1
Дальше меняем статус канала с 5 на 6, чтобы другие потоки игнорировали его и занимались работой с другими каналами. Обращаю внимание, чтобы мы могли определить был, изменен статус или нет, определяем, что менять статус будем только тогда, когда статус не равен значению 6 (другой поток еще не изменил статус). Если выполнять запрос в Зеннопостере в режиме "Без ответа" - то в переменную нам сохранится либо количество измененных строк, либо ноль. Если значение больше чем ноль - значит, статус изменился, а значит, мы можем продолжать работу - иначе - необходимо будет получить другой канал (или закончить работу шаблона).

Код:
UPDATE channel SET channel.0x300status0x300 = 6 WHERE channel.id = "{-Variable.id_channel-}" AND channel.0x300status0x300 <> 6 LIMIT 1
Вспоминаем, что в прошлых шаблонах удаляли пустые строки - данный запрос перекочевал оттуда сюда - думаю, лишним не будет, хотя, если изначально проверять данные, перед добавлением их в базу на предмет пусты - то вероятнее всего данный запрос можно будет не выполнять, так как пустых строк в базе данных не будет.

Код:
DELETE FROM channel WHERE channel.id="";
Дальше мы подсчитываем количество видео с статусом 0 (отмечу, что работать уже мы будем с таблицей в которой хранятся видео - до этого времени мы работали с таблицой в которой хранилась информация о каналах).

Код:
SELECT Count(video.id_video) FROM video WHERE video.0x300status0x300 = 0 AND video.id_channel = "{-Variable.id_channel-}"
Если в базе данных нет видео с таким статусом - значит пора изменить статус наканала в значение 7 (это будет говорить о том, что информация о всех видео уже загружена в базу).

Код:
UPDATE channel SET channel.0x300status0x300 = 7 WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1
В противном случае мы получим с базы данных 50 идентификаторов каналов (да, информацию о видео мы можем получать пачками через API - в этом и прелесть).

Код:
SELECT video.id_video FROM video WHERE video.id_channel = "{-Variable.id_channel-}" AND video.0x300status0x300 = 0 LIMIT 50
Конечно же изменим статус канала в значение 7 чтобы освободить его, если в переменной в результате выполнения предыдущего запроса пусто.

Код:
UPDATE channel SET channel.0x300status0x300 = 7 WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1
Если же мы получили идентификаторы, то шаблон уже обращается к API описанными ранее способами, получает данные, разбирает по переменных, формирует значения для запроса - и вот только потом отправляет данный запрос. Здесь отмечу, что в случае обнаружения дубля обновляются все поля - дело в том, что если мы скачали статистику вчера, то сегодня у нас информация по количеству просмотров уже изменилась - а значит - есть смысл перекачивать информацию повторно чтобы держать её в актуальном состоянии.

Код:
INSERT INTO video (video.id_video, video.id_channel, video.title, video.discription, video.0x300status0x300, video.categoryid, video.default_language, video.privatstatus, video.license, video.stat_view, video.view_count, video.likecount, video.dislikecount, video.favoritecount, video.commentcount) VALUES {-Variable.query_video_update-} ON DUPLICATE KEY UPDATE video.title=VALUES(title), video.discription=VALUES(discription), video.0x300status0x300=VALUES(0x300status0x300), video.categoryid=VALUES(categoryid), video.default_language=VALUES(default_language), video.privatstatus=VALUES(privatstatus), video.license=VALUES(license), video.stat_view=VALUES(stat_view), video.view_count=VALUES(view_count), video.likecount=VALUES(likecount), video.dislikecount=VALUES(dislikecount), video.favoritecount=VALUES(favoritecount), video.commentcount=VALUES(commentcount)
И вот, после добавления информации об видео в базу данных осталось еще добавить теги. Так как теги разбиты у меня на две таблички - то добавляются они по очереди двумя запросами. В первом добавляются теги в табличку с тегами, и при обнаружении дубликата счетчик в базе данных увеличивается на 1 (таким образом можно будет обнаружить самые популярные теги).

Код:
INSERT INTO tag (id) VALUES {-Variable.query_tag-} ON DUPLICATE KEY UPDATE count=count+1
А уже после добавления тегов - добавляются теги и идентификаторы видео в другую табличку - для того, чтобы в дальнейшем можно было делать выборку роликов по определенным тегам.

Код:
INSERT INTO video_tag (video_tag.id_video, video_tag.id_tag) VALUES {-Variable.query_tag-} ON DUPLICATE KEY UPDATE video_tag.0x300timestamp0x300=now()
В завершение возвращаем статус канала в значение 5 (чтобы следующий поток смог взять следующие 50 роликов). Здесь также требуется замечание о том, что в данном случае каналам изменяются статусы вначале работы шаблона, так как опираемся мы на данные с базы, а не с API.

Код:
UPDATE channel SET channel.0x300status0x300 = 5 WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1

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

И так, обратно мы берем канал и изменяем ему статус. В этот раз уже канал со статусом 7 и количеством видео больше 0 (ведь если нет видео - то комментариев там точно нет).

Код:
SELECT channel.id FROM channel WHERE channel.0x300status0x300 = 7 AND channel.videoCount > 0 LIMIT 1
Уже знакомый запрос удаления пустых строк с базы данных будет использован если вдруг мы ничего не получим с базы данных.

Код:
DELETE FROM channel WHERE channel.id="";
Дальше статус нашего канала должен мигрировать с 7 на 8 - по аналогии с предыдущими шаблонами.

Код:
UPDATE channel SET channel.0x300status0x300 = 8 WHERE channel.id = "{-Variable.id_channel-}" AND channel.0x300status0x300 <> 8 LIMIT 1
После чего подсчитываем количество видео с комментариями и статусом 1.

Код:
SELECT Count(video.commentcount) FROM video WHERE video.id_channel = "{-Variable.id_channel-}" AND video.commentcount > 0 AND video.0x300status0x300 = 1 LIMIT 1
Если количество видео будет больше чем ноль, значит можно получить с базы данных идентификатор видео и токен странички с комментариями (вдруг уже другой поток скачал часть комментариев и оставил метку нам).

Код:
SELECT video.id_video, token_comment FROM video WHERE video.id_channel = "{-Variable.id_channel-}" AND video.0x300status0x300 = 1 AND video.commentcount > 0 LIMIT 1
Если мы ничего не получили - значит на данном видео еще нет комментариев либо все комментарии загружены в базу данных. А значит - меняем статус для канала (освобождаем его).

Код:
UPDATE channel SET channel.0x300status0x300 = 9 WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1
Иначе меняем статус видео, и добавляем токен чтобы другой поток смог продолжить нашу работу - скачать очередные комментарии.

Код:
UPDATE video SET video.0x300status0x300 = 1, video.token_comment = "{-Variable.token_list_comment-}"  WHERE video.id_video = "{-Variable.id_video_comment-}" LIMIT 1
Обратно, по условию, освобождаем канал, считая, что все комментарии скачали (служить этим признаком может отсутствие токена в ответе API).

Код:
UPDATE channel SET channel.0x300status0x300 = 9 WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1
Изменяем статус видео в значение 2, изменяем токен.

Код:
UPDATE video SET video.0x300status0x300 = 2, video.token_comment = "{-Variable.token_list_comment-}"  WHERE video.id_video = "{-Variable.id_video_comment-}" LIMIT 1
Если другой поток еще должен докачивать комментарии - меняем статус для канала в значение 7.

Код:
UPDATE channel SET channel.0x300status0x300 = 7 WHERE channel.id = "{-Variable.id_channel-}" LIMIT 1
Дальше мы добавляем собранных авторов комментариев в базу данных, при обнаружении дублей - обновляем временную метку.

Код:
INSERT into channel(channel.id) VALUES {-Variable.query_commentators-} ON DUPLICATE KEY UPDATE 0x300timestamp0x300 = now();
И под конец работы нашего шаблона добавляем комментарии, которые были скачаны.

Код:
INSERT into 0x300comment0x300(0x300comment0x300.id_video, 0x300comment0x300.id_comment, 0x300comment0x300.authorChannelId, 0x300comment0x300.textDisplay, 0x300comment0x300.publishedAt, 0x300comment0x300.updatedAt, 0x300comment0x300.likeCount, 0x300comment0x300.parentId) VALUES {-Variable.query_comment-} ON DUPLICATE KEY UPDATE 0x300comment0x300.likeCount = VALUES(likeCount);
4.jpg

Выше описан план, а значит пора приступать к делу - создать пачку шаблонов для Зеннопостера, которые быстро, без использования браузера и с использованием APIv3 YouTube будут получать необходимую общедоступную информацию.
Собирать будем информацию о канале, видео, комментарии к видео. После чего добавим всю информацию в базу данных. Чтобы в дальнейшем можно было делать выборку данных с базы данных поопределенным нами параметрам (тут уже творческая работа).
Так вот шаблонов будет несколько - один будет собирать только информацию о канале, второй будет собирать только список видео на канале, третий будет собирать только статистику просмотров, описания и теги к роликам, и последний - будет собирать комментарии к этим видеороликам.
Каждый из шаблонов содержит входящие настройки, из которых подхватывает ключ для доступа к API YouTube и данные для доступа к базе данных (логин, пароль, сервер, имя базы данных). Также во входящих настройках добавлены значения по умолчанию, которые в дальнейшем заменяются шаблоном после получения данных с базы (добавлены для того, чтобы иметь возможность протестировать шаблоны/запросы без базы данных).


Логика работы шаблона для Зеннопостера, который, с помощью API собирает общедоступную информацию с канала YouTube, выглядит следующим образом:
Прежде всего, шаблон получает входящие настройки и, используя полученные значения, обращается к базе данных за получением идентификатора канала (информацию о котором требуется получить). Предполагается, что в базе данных уже добавлен список каналов. Если это не так - то шаблон попытается удалить пустые строки и закончит работу.
Если шаблон получил с базы данных идентификатор канала, то следующим действием он попытается изменить статус канала в базе данных - и если изменение было произведено успешно - продолжит работу, иначе - попытается получить следующий идентификатор канала. Данный подход применен с целью обеспечения многопоточности шаблона - каждый поток будет получать другой идентификатор канала - а значит, разные потоки не будут выполнять одну и ту же работу.
Так вот, если идентификатор канала получен, статус изменен успешно. Определяется это по количеству измененных строк в базе данных. Если база вернула 0, значит ничего не изменено, а значит, статус не изменился, если же база данных возвращает 1 – значит, изменена одна строка - а значит, статус изменился, то шаблон может обратиться к API YouTube, используя ключ доступа (API KEY) обычным GET запросом с целью получения необходимой информации.
После выполнения запроса в переменной, которая используется для временного хранения результата, будет содержаться масив данных в формате JSON. В зависимости от навыков работы с Зеннопостером эти данные необходимо разобрать попеременных для дальнейшего сохранения в таблицу, список, файлы или для формирования запроса к базе данных.
Я определился с сохранением данных в базу данных MySQL и разбором полученного JSON с помощью регулярных выражений в одном сниппете C# кода. Результатом успешного выполнения сниппета является строка с подготовленными значениями для добавления в базу данных. Собственно переменная с данным результатом и будет использоваться в SQL запросе экшина для работы с базами данных.
После добавления данных о канале, которые были собраны, есть необходимость изменить статус канала - освободить его для возможности работы с ним другими шаблонами. После чего шаблон заканчивает работу. При желании в любом месте шаблона можно добавить уведомления в лог, чтобы иметь возможность наблюдения за состоянием переменных - но, после того, как шаблон оттестирован, я удалил все уведомления, оставив только последнее, которое оповещает об успешном добавлении информации о канале.
Итого, в результате выполенния данного шаблона в базу данных будет добавлена общая информация о канале, среди нее будет сохранен идентификатор плейлиста всех загруженных роликов на канал, который и будет использован в следующем шаблоне.


Логика работы шаблона для Зеннопостера, который собирает список загруженных видео на канал YouTube без использования браузера (но с использованием YouTube API) выглядит следующим образом.
Прежде всего, шаблон получает с входящих настроек данные, для доступа к базе данных, и ключ доступа к YouTube API который будет использоваться для получения от YouTube информации (в данном случае списка видео на канале).
Используя полученые с входящих настроек значения, шаблон обращается к базе данных, запрашивая идентификатор канала, список видео которого еще не сохранен в базу данных. Если в результате выполнения запроса ничего не было получено - делаем вывод, что в базе данных либо есть пустые строки (получена пустая строка - в таком случае удалим пустые стоки с базы данных соответствующим запросом). Если же был получен идентификатор канала – значит, шаблон следующим запросом изменит статус, обозначив тем самым для других потоков Зеннопостера, что данный канал сейчас обрабатывается - таким образом, следующие потоки не смогут получить для работы этот же идентификатор канала - данная манипуляция позволяет реализовать многопоточную работу.
Дальше шаблон получает количество видео на канале (эта информация хранится в базе данных как результат выполнения работы предыдущего шаблона) и подсчитывает количество уже добавленных идентификаторов видео в базу данных. Если количество роликов на канале больше, чем количество добавленных идентификаторов видео в базе данных мы можем сделать вывод, что на канале появились новые ролики - а значит необходимо перейти к загрузке списка роликов с данного канала. В противном случае - изменяем статус канала (освобождая его для других потоков и шаблонов) и заканчиваем выполнение шаблона.
Если же есть необходимость скачать список видео - то проверяем, не хранится ли случайно в базе данных токен, который предназначен для получения определенной странички с роликами на интересующем нас канале. Одновременно получаем с базы данных и идентификатор плейлиста, в котором хранятся все загруженные видео на канал.
Разделив по разделителю (предыдущим запросом к базе данных мы получили идентификатор плейлиста и токен и сохранили их в одной переменной) идентификатор плейлиста и токен мы можем проверить есть пустой токен у нас или нет. Если токена нет - отправляем запрос к API без использования токена. Если токен есть – значит, отправляем запрос с токеном.
В результате обращения к API YouTube мы получим масив данных в формате JSON, который, как и в предыдущем шаблоне, нам необходимо разобрать регулярными выражениями попеременных и сформировать запрос для добавления в базу данных.
После добавления списка роликов в нашу базу данных, шаблон должен освободить канал, изменив его статус, после чего работа шаблона заканчивается успешным выполнением и уведомлением (при необходимости).
Естественно, что прежде чем удалить все уведомления в лог, которые оповещали на каждом шаге, как происходит выполнение, я протестировал шаблон, и убедившись, что каждая переменная принимает корректные значения - удалил их.
В итоге выполнения работы данного шаблона в базе данных у нас уже хранится как информация о канале (результат работы предыдущего шаблона), так полный список загруженных видео на канал (или частичный - тогда следующие потоки догрузят весь список) с краткой информацией о видео. Но, так как нам необходимы теги к видео и статистика просмотров - это уже более подробная информация - а значит, получать эти данные будет следующий шаблон.


Как и предыдущие шаблоны Зеннопостера для сбора общедоступной информации о каналах на YouTube с использованием API - данный шаблон также не будет использовать браузер, будет сохранять результат своей работы в базу данных MySQL, данные для доступа к API и к нашей базе данных будет получать с входящих настроек. Впрочем, и логика работы данного шаблона будет аналогичной с предыдущими шаблонами, но с некоторыми изменениями.
Шаблон получит идентификатор канала YouTube с базы данных и изменит для него статус, и в случае успеха проверит количество роликов, к которым еще не была скачана информация. Если полученное значение будет больше нуля - значит можно взять первых 50 роликов (да, получать информацию дальше будем пачками) и отправить запрос к API на получение данных.
Результатом, как и раньше, будет масив данных в формате JSON, а значит, уже знакомый сниппет разберет его регулярными выражениями попеременных и сформирует запросы к базе данных на добавление информации о видео и добавление информации о тегах.
В конце шаблон освободит канал для других потоков и шаблонов, изменив статус, закончит работу уведомлением в лог. Обратно-таки, в процессе тестирования шаблона уведомлений было много - но когда была запущена рабочая версия - все уведомления были убраны с шаблона.
В итоге в результате выполнения шаблона в базе данных уже будет сохранена подробная информация о 50 видеороликах (идентификаторы которых мы получали с базы данных в начале выполнения шаблона), а также будут сохранены теги, которые автор ролика вводил для лучшего обнаружения ролика потенциальными зрителями.


Для сбора комментариев, которые пользователи размещают под видео на YouTube, будем придумывать шаблон, который, как и предыдущие, не будет использовать браузер и сможет получать комментарии, используя API KEY. Запрос, который используется, был описан выше - здесь же предлагаю рассмотреть логику работы шаблона.
Получив идентификатор канала с базы данных, шаблон изменит его статус для обеспечения многопоточности, после чего сравнив количество комментариев, написанных для видео, и количество комментариев в базе шаблон определяет завершать ему работу или идти отправлять запрос на получение комментариев от YouTube.
Допустим, что необходимо собрать комментарии - тогда мы получаем с базы данных идентификатор видео и токен, при этом, если токен присутствует – значит, отправляем к YouTube запрос с токеном, иначе - без токена, после чего разобрав результат попеременных, формируем запрос к базе данных, и добавляем данные в базу.
В промежутке нужно будет еще проверять пришел ли нам токен в ответ - если пришел, добавляем его в базу и изменяем статус канала, если не пришел – значит, что все комментарии скачаны - обратно изменим статус канала.
Завершение шаблона, как и в предыдущих шаблонах, это изменение статуса канала, после чего работа над каналом закончена, и можно показать уведомление в лог, а другие потоки, или шаблоны, уже могут использовать полученную информацию, получая её с базы данных.
Итогом выполнения данного шаблона является добавленный список комментариев, которые добавлены под видео роликом на YouTube, а при многократном выполнении все комментарии будут сохранены в базу данных. Также данный шаблон автоматически пополняет базу данных новыми каналами комментаторов - что позволяет постепенно наполнять базу данных новыми каналами и делать в дальнейшем выборки самих активных зрителей.
P.S. Возможно после прочтения статьи откорректирую внешний вид, исправлю ошибки, залью картинки на форум и заменю.
 

Вложения

Для запуска проектов требуется программа ZennoPoster.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...

Для того чтобы запустить шаблон, откройте программу ZennoPoster. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.

Последнее редактирование:

25region

Client
Регистрация
26.09.2013
Сообщения
186
Благодарностей
54
Баллы
28
шаблоны примерчики с mysql круть, спс
 
  • Спасибо
Реакции: BAZAg

Geograph

Client
Регистрация
16.02.2014
Сообщения
169
Благодарностей
76
Баллы
28
Оформление на пять с плюсом

Дизайнером подрабатываешь? :-)
 
  • Спасибо
Реакции: vredin, Slava и BAZAg

Sanekk

Client
Регистрация
24.06.2016
Сообщения
646
Благодарностей
235
Баллы
43
креативное оформление статьи прям очень порадовало)))
парсинг инфы с ютуба наталкивает на размышления, статья на 5++ буду однозначно голосовать
 
  • Спасибо
Реакции: BAZAg

sydoow

Client
Регистрация
22.06.2011
Сообщения
197
Благодарностей
101
Баллы
28
Для меня первая полезная статья в этом конкурсе.
Буду голосовать за Юрия в любом случае, тк по мимо этой статьи у Юры есть канал на Ютубе, на котором я получил некоторую полезную инфу (например узнал про софт mRemoteNG), хотя последние ролики с вычиткой статей я считаю трешем, но это не моё дело и я догадываюсь для чего он это делает :-)
Спасибо Юре :-)

ps: на аве такой злой дядька, а на стримах - добрый парень :D
 
  • Спасибо
Реакции: BAZAg и Valiksim

daymos

Client
Регистрация
11.11.2009
Сообщения
768
Благодарностей
211
Баллы
43
Столько спойлеров, я аж устал клацать
 
  • Спасибо
Реакции: kagorec и BAZAg

Valiksim

Client
Регистрация
14.04.2012
Сообщения
1 291
Благодарностей
286
Баллы
83
Столько спойлеров, я аж устал клацать
Надо бы сказать разработчикам, пусть сделают возможность в настройках задать "Открытые спойлеры". Такое есть на большинстве форумов
Понимаю, зря написал, но всё-таки. Такое оформление имеет большие преимущества, но, создаёт небольшие неудобства
 
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
418
Благодарностей
554
Баллы
93
25region, Спасибо! При желании данные шаблоны легко превращаются в парсеры чего угодно в базу данных.
Geograph, Спасибо! Статью писал в программе Mindjet MindManager - и выбрал одно из стандартных оформлений которое понравилось (чтобы сделать скриншоты), а вот спойлеры придуманы специально, чтобы не пугать людей большим количеством знаков - слона нужно кушать по кусочкам.
Sanekk, Спасибо! Посмотрите например канал Webdriver Torso - думаю наши Зенки на больше способны (как минимум смогут придумать заголовки, теги, ключи, комментарии, предварительно собрав их шаблонами из статьи).
alekwuy, Несколько лет назад я комментировал блоги - тогда и выработал эту привычку.
sydoow, Спасибо! Статьи были прочитаны на одном дыхании в течении нескольких суток, процесс записан на видео и залит на ютуб. Цель - обратить внимание людей ютуба на то, что существует такой форум, такая программа, и я это не сам придумал - а люди сами поделились своими историями в своих статьях. Обратив их внимание, вероятнее всего им не понравится мое произношение каких-либо слов, возможно звук, возможно мое лицо - но если тема им интересна - они пожелают пойти почитать исходник. И вот тут они смогут перейти по партнерской ссылке (правда пока не разобрался как её правильно сформировать именно на конкретные статьи - из-за чего пока их там нет). Естественно, что вне зависимости нравится кому-то это или нет - ролики будут появляться, так как в перспективе будут давать мне доход (либо с трафика, либо с рекламы, либо кто-то обратится с вопросом и в итоге превратится в клиента).
Valiksim, Спасибо! Рад, что понравилась моя работа.
daymos, 52 спойлера... Но в этом есть свои положительные стороны - поведенческие факторы на форуме улучшаются - трафика с поиска больше придет.
статья-знаки.jpg
 
  • Спасибо
Реакции: Hannes, Sanekk и Valiksim
Регистрация
27.05.2015
Сообщения
128
Благодарностей
41
Баллы
28
Юрий, а можете выложить Mind Map к данной статье? Очень неудобно эти спойлеры разворачивать, но идея с Mind Map это конечно 5 баллов!
 
  • Спасибо
Реакции: BAZAg

Buch

Client
Регистрация
15.02.2016
Сообщения
259
Благодарностей
75
Баллы
28
Очень понравилось,спасибо!
 
  • Спасибо
Реакции: BAZAg

DenisK

Client
Регистрация
28.06.2016
Сообщения
239
Благодарностей
86
Баллы
28
Хорошая, статью... Спасибо Юра.
 
  • Спасибо
Реакции: BAZAg

Redsmokky

Client
Регистрация
06.10.2015
Сообщения
221
Благодарностей
90
Баллы
28
Я ждал эту статью)) Как всегда на высоте, все по-полочкам))
 
  • Спасибо
Реакции: BAZAg

Lord_Alfred

Client
Регистрация
09.10.2015
Сообщения
3 208
Благодарностей
2 703
Баллы
113
Юрий, добротная, качественная и отличная статья!

Давно уже интересно: откуда у тебя такие хорошие знания по проектированию СУБД? Чем ты занимался до заработка в инете?
 
  • Спасибо
Реакции: BAZAg

NoN

Пользователь
Регистрация
04.01.2015
Сообщения
184
Благодарностей
22
Баллы
18
Нужно было сразу и ссылку на свой ютуб канал оставить)
 
  • Спасибо
Реакции: BAZAg и Valiksim

samsonnn

Client
Регистрация
02.06.2015
Сообщения
1 126
Благодарностей
586
Баллы
113
То что нужно, спасибо Юр :ay:
 
  • Спасибо
Реакции: BAZAg

25region

Client
Регистрация
26.09.2013
Сообщения
186
Благодарностей
54
Баллы
28
25region, Спасибо! При желании данные шаблоны легко превращаются в парсеры чего угодно в базу данных.
Порой возникают ситуации когда списков и таблиц не хватает, для решений в большинстве случаев колхозю индексно ориентированные таблицы на txt файлах, но все это медленно и мягко говоря не стабильно при большом количестве файлов. а мусклул крут и безлимитен, оч понравился ман и примеры.
 
Последнее редактирование:
  • Спасибо
Реакции: BAZAg

Troll_UA

Client
Регистрация
11.04.2016
Сообщения
121
Благодарностей
31
Баллы
28
Юрий, если не сложно можешь немножко описать по типам полей в базе данных. Какой тип поля для чего использовать.
 
  • Спасибо
Реакции: BAZAg

emel

Client
Регистрация
21.02.2015
Сообщения
66
Благодарностей
11
Баллы
8
Нормально. Самое то для новичков.
 
  • Спасибо
Реакции: BAZAg

Astraport

Client
Регистрация
01.05.2015
Сообщения
3 122
Благодарностей
2 150
Баллы
113
а есть какая-то существенная разница?
ZennoPoster десктопное приложение. Если есть какие-то задачи подключать другие, но уже серверные приложения, то MySQL, но если полученные данные и дальше будут использоваться Зенно, то проще SQLite.
 
  • Спасибо
Реакции: deninsto и BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
418
Благодарностей
554
Баллы
93
Aleksandr Tr4sh, Спасибо! Простите, я не готов предоставить черновик с которым работал на общее обозрение. При необходимости просмотреть целую статью без спойлеров можете просто отключить JS в браузере (либо открыть страничку в Project Maker с отключеным JS) - и разворачивать спойлеры не нужно будет.
Buch, Спасибо! Старался предоставить материал так, как его вижу я.
DenisK, Спасибо! Буду рад, если предложенная информация принесет пользу.
Redsmokky, Спасибо! Я сам не уверен был в том, что у меня получится - писал статью, а получилась дипломная работа :-)
Lord_Alfred, Спасибо! Просто была острая необходимость изучить работу с БД с целью заработка - а это лучшая мотивация.
NoN, Спасибо! В статью я вставлял ссылки на ролики с своего канала - из них при необходимости можно попасть и на канал. Но, старичкам форума он врятли будет интересным, а новички думаю без проблем смогут его найти на ютубе и без моей помощи.
samsonnn, Спасибо! Рад, что статья понравилась. Я видел, что ты где-то писал что есть затруднения по работе с многопотоком - думаю когда начнешь работать с базами данных - то такие проблемы как пересечения кучи списков, и содержание информации о множестве сайтов в многих списках уже не понадобится. Впрочем статья затрагивает моменты по работе с многопотоком.
25region, с MySQL есть свои проблемы - отталкиваться в выборе базы данных, таблиц и списков, облака нужно от необходимости (потребности). К примеру, год назад я работал с криптовалютными кранами. Покупал выделенные сервера. Мне было важно в любой конкретный момент времени иметь возможность наблюдать какие результаты выдают мои шаблоны у меня и у людей у которых работали мои шаблоны. Так в вот тогда я узнал что у баз данных есть такая штука как превышение лимита входящих подключений (6 серверов в 350 потоков которые подключались к базе каждую минуту примерно выдерживала, но подключить больше серверов к одной базе я не знал как - вероятно нужно было на сервере устанавливать PHP и обращаться к скрипту - чтобы количество одновременных подключений не превышать - но я с этим еще не разобрался). В том конкретном случае стоящим внимания было решение отправки данных в таблицы гугла - не смотря на ограничения на количество ячеек - со своей работой (приемом большого количества данных с большого количества серверов) гугл справлялся без проблем.
Astraport, потому что базы данных могут быть не только на компьютере, но и установлены на хостингах, а там установлена MySQL, и прежде чем устанавливать её себе на компьютер и на сервер - я пользовался хостингом на котором установлен мой блог, потом ставил денвер... Как-то просто SQLite не попала в поле зрения в момент, когда мне это было необходимо (и не было человека, который бы рассказал как работать с ней).
Sanekk, возможно разница есть - но кто-то из знакомых меня все же предупреждал, чтобы я не тратил время на SQLite. Не имея дела с ней - мне сложно предположить лучше она или хуже.
Valiksim, да, изучал в институте, курсовой проект делал по базам данных - но там работа не была с MySQL - и относился я тогда к базам данных примерно как к программе Excel (не видел существенной разницы, более того мне Excel тогда казался удобнее).
Troll_UA, Я в основном использую int, bigint, varchar, text, timestamp, decimal. Первый тип данных - для всех счетчиков и статусов. Второй - когда числовое значение может быть значительно большим, например 18 значным. Третий тип данных когда сохраняю любой текст до 255 знаков, если текст больше - использую четвертый указанный выше тип данных. Для временных меток соответствующий тип данных timestamp и для денег и криптовалюты - decimal. Но, если честно я не придаю значения этому и не запоминаю - при необходимости - спрашиваю у гугла какой тип данных лучше использовать для тех или инных данных.
emel, Спасибо. Буду рад, если новички найдут время на прочтения статьи - я когда был новичком очень сильно упирался и не хотел разбираться с базами данных и запросами.
Astraport, у меня часто выключают свет, мне было важно, чтобы база данных находилась на независимом от моего домашнего электричества месте - терять данные это всегда неприятно. MySQL с этим хорошо справляется. Но, не исключаю, что кому-то будет удобнее работать с SQLite.
 

bstshell

Client
Регистрация
03.06.2015
Сообщения
56
Благодарностей
5
Баллы
8
Покопался в справке Youtube API и никак не могу понять как использовать поиск. Можете скинуть пример запроса?
 
  • Спасибо
Реакции: BAZAg

BAZAg

Client
Регистрация
08.11.2015
Сообщения
418
Благодарностей
554
Баллы
93
Покопался в справке Youtube API и никак не могу понять как использовать поиск. Можете скинуть пример запроса?
Код:
https://www.googleapis.com/youtube/v3/search?part=id&q=что ищем&type=video&key={YOUR_API_KEY}
 
  • Спасибо
Реакции: Сибиряк и arhip1985

alex_shv

Client
Регистрация
31.03.2015
Сообщения
50
Благодарностей
20
Баллы
8
Супер!
Спойлеры не мешают...)))
 
  • Спасибо
Реакции: BAZAg

Gfoblin

Client
Регистрация
30.05.2013
Сообщения
4 019
Благодарностей
812
Баллы
113
Народ сори за офтоп, а нету жеж фида у ютьюба или я чето пропустил, ну там допустим все видосы за последний день :-) только парсить?
 
  • Спасибо
Реакции: BAZAg

Кто просматривает тему: (Всего: 1, Пользователи: 0, Гости: 1)