Статьи

Изучение публичных событий Github с помощью PHP и Google BigQuery

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

Github Logo

Что такое публичные мероприятия Github?

События Github — это взаимодействия пользователей, такие как добавление, объединение, создание репозиториев и т. Д. Это похоже на сохранение истории Github. Тем не менее, мы ограничены последними 300 событиями, и это проблема, если вы хотите искать данные всей истории.

Илья Григорик хотел отслеживать свой проект с открытым исходным кодом, но из-за ограничения API публичных событий Github он решил создать веб-сайт GithubArchive, где он запрашивает API Github и сохраняет результаты. Вы можете запросить архив со ссылками, такими как http://data.githubarchive.org/2015-01-01-15.json.gz и вы получите архив, содержащий полезную нагрузку JSON. Это решение не очень эффективно и не помогает запрашивать историю данных, поэтому, когда Google BigQuery был выпущен, Григорик переместил все свои данные в новое хранилище и сделал его общедоступным.

Почему BigQuery?

Google BigQuery был создан для решения проблемы задержки запросов. Когда вы имеете дело с большими данными, вам необходимо иметь правильное оборудование и инфраструктуру для правильной обработки нагрузки. Теперь у вас есть возможность перенести свою базу данных только для добавления в инфраструктуру Google и увидеть миллионы строк данных, обработанных за считанные секунды.
Если вы не знакомы с API Google, обязательно ознакомьтесь с этим руководством о начале нового проекта Google API . После этого обязательно включите API BigQuery на консоли разработчиков Google.

Настройка среды

Я буду использовать Laravel в качестве своего предпочтительного фреймворка и Homestead Improved для моей виртуальной машины. Мы получим наши учетные данные Google из файла config/google.php , и в соответствии с правилами безопасности Laravel я .env эти учетные данные в файле .env .

 // config/google.php return [ 'app_name' => env('app_name'), 'client_id' => env('client_id'), 'client_secret' => env('client_secret'), 'api_key' => env('api_key') ]; 
 // .env APP_DEBUG=true app_name='Optional app name' client_id='CHANGE IT' client_secret='CHANGE IT' api_key='CHANGE IT' 

Я также создам нового поставщика услуг для хранения привязок наших служб Google.

 // app/Providers/BigQueryServiceProvider.php class BigQueryServiceProvider extends ServiceProvider { public function register() { $this->app->bind('GoogleClient', function () { $googleClient = new \Google_Client(); $googleClient->setAccessToken(\Session::get("token")); return $googleClient; }); $this->app->bind('bigquery', function () { $googleClient = \App::make('GoogleClient'); $bigquery = new \Google_Service_Bigquery($googleClient); return $bigquery; }); } } 
 // config/app.php // ... 'providers' => [ // ... 'App\Providers\BigQueryServiceProvider', ] 

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

 // app/Http/Middleware/GoogleLogin.php class GoogleLogin { public function handle($request, Closure $next) { $ga = \App::make('\App\Services\GoogleLogin'); if (!$ga->isLoggedIn()) { return redirect('login'); } return $next($request); } } 
 // app/Kernel.php protected $routeMiddleware = [ // ... 'google_login' => '\App\Http\Middleware\GoogleLogin' ]; 

Google BigQuery Query Console

Прежде чем мы начнем работать с BigQuery с использованием библиотеки PHP, давайте начнем исследовать консоль BigQuery Query . На консоли есть кнопка Compose Query , чтобы вы могли писать свои запросы. Ниже у нас есть ссылка Query History которая показывает историю наших запросов. Поскольку на наши запросы потребуется некоторое время, мы можем выполнить запрос как задание и через некоторое время запросить его статистику — ссылка «Журнал Job History содержит список текущих заданий.

BigQuery Console

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

Table schema

Google BigQuery API и Github

В качестве примера, давайте попробуем получить десятку популярных проектов на Github. Я буду определять популярность как количество вилок. Класс Google_Service_Bigquery отвечает за все типы взаимодействий с Google BigQuery API. Ранее я ввел термин « jobs , что означает, что мы можем выполнить запрос в фоновом режиме и со временем получить его статус, чтобы увидеть, завершен он или нет.

 // app/Http/routes.php Route::any('/topTen', ['middleware' => 'google_login', 'as' => 'topTen', 'uses' => 'BigQueryAPIController@topTen']); // app/Http/Controllers/BigQueryAPIController.php class BigQueryAPIController extends Controller { public function __construct() { $this->bigqueryService = \App::make("bigquery"); } public function topTen() { $projectID = 'modular-robot-22'; $query_str = "SELECT repository_url, MAX(repository_forks) as max_forks" . " FROM githubarchive:github.timeline" . " GROUP EACH BY repository_url" . " ORDER BY max_forks DESC" . " LIMIT 10"; $query = new \Google_Service_Bigquery_QueryRequest(); $query->setQuery($query_str); $result = $this->bigqueryService->jobs->query($projectID, $query); $fields = $result->getSchema()->getFields(); $rows = $result->getRows(); dump($fields); foreach ($rows as $row) { dump($row->getF()); } } } 

Идентификатор проекта можно найти в консоли разработчиков Google . Строка запроса respository_url и MAX(repository_forks) . Метод getSchema возвращает экземпляр Google_Service_Bigquery_TableSchema который содержит имена выбранных столбцов из ответа, а метод getRows возвращает итеративный список Google_Service_Bigquery_TableRow . Вывод выглядит следующим образом.

Top Ten Query Dump

githubarchive:github.timeline данных githubarchive:github.timeline устарел и больше не будет обновляться. Новый способ работы с данными — через определенный временной диапазон (набор данных года, набор данных месяца, набор данных дня); Вы можете посетить githubarchive, чтобы узнать больше об этом. Теперь мы должны обновить наш запрос выше, чтобы работать с прошлогодними данными.

 // app/Http/Controllers/BigQueryAPIController.php public function topTen() { $projectID = 'modular-robot-22'; $query_str = "SELECT repository_url, MAX(repository_forks) as max_forks" . " FROM githubarchive:year.2014" . " GROUP EACH BY repository_url" . " ORDER BY max_forks DESC" . " LIMIT 10"; //... } 

Десять лучших репозиториев по языкам

Мы адаптируем предыдущий запрос для извлечения репозиториев определенного языка. Наша разметка представления будет содержать форму и набор языковых опций.

 // resources/views/home.blade.php <form action="/" method="POST" class="form-inline"> <label for="language">Language: </label> <select name="language" id="language" class="form-control"> <option value="PHP">PHP</option> <option value="JavaScript">JavaScript</option> <option value="CSS">CSS</option> <option value="Python">Python</option> </select> <input type="submit" class="form-control" value="Submit"/> </form> 

Когда пользователь отправляет форму, мы получаем выбранный язык и заполняем условие в нашем запросе SQL. Поскольку мы напечатаем наш результат запроса в виде таблицы, мы отделим часть заголовка таблицы от тела таблицы.

 // app/Http/Controllers/BigQueryAPIController.php public function topTen() { if (!\Input::has('language')) { return \View::make('home', ['repos' => null]); } $language = \Input::get('language', 'PHP'); $projectID = 'modular-robot-647'; $query_str = "SELECT repository_url, MAX(repository_forks) as max_forks" . " FROM githubarchive:year.2014" . " WHERE repository_language='$language'" . " GROUP EACH BY repository_url" . " ORDER BY max_forks DESC" . " LIMIT 10"; $query = new \Google_Service_Bigquery_QueryRequest(); $query->setQuery($query_str); $result = $this->bigqueryService->jobs->query($projectID, $query); // getting the table header $fields = $result->getSchema()->getFields(); // query response rows $repos = $result->getRows(); return \View::make('home', ['repos' => $repos, 'tableHeader' => $fields]); } 

Единственное, что изменилось по сравнению с предыдущим запросом, это условие where , которое фильтрует языки по пользовательскому вводу. При распечатке таблицы результатов я старался сделать вещи общими для большинства запросов.

 // resources/views/home.blade.php @if($repos) <table class="table table-hover"> <tr> @foreach($tableHeader as $item) <th>{{$item->getName()}}</th> @endforeach </tr> @foreach($repos as $repo) <tr> @foreach($repo->getF() as $item) <td>{{$item->getV()}}</td> @endforeach </tr> @endforeach </table> @else <h2>Nothing to show</h2> @endif 

Метод getF() возвращает содержимое строки, а метод getV() возвращает содержимое ячейки. Вы можете проверить значения результатов, сбросив имена классов и пройдя через свойства.

PHP top ten

Похоже, что CodeIgniter был на вершине, когда я тестировал это, но на момент написания статьи это не так — Laravel является самой популярной средой PHP на Github. Обязательно зайдите на страницу трендовых репозиториев Github, чтобы увидеть данные почти в реальном времени.

Если вы решили работать с данными, добавленными после 01/01/2015 , схема также будет содержать вложенные записи плюс поле полезной нагрузки в кодировке JSON. Это относится и к работе с дневными наборами данных — вы можете использовать консоль Google BigQuery для проверки схемы набора данных. BigQuery имеет несколько полезных функций JSON для работы с данными в кодировке JSON, обязательно ознакомьтесь с ними.

Вывод

В этой статье мы рассказали о публичных мероприятиях Github и о том, как их можно использовать через BigQuery. Заключительная демонстрация включает в себя пример базового использования, но вы можете поэкспериментировать с API и подготовиться к ежегодной проблеме данных Github с некоторыми интересными фактами о данных Github. Что вы думаете об API Github Events? У вас есть какие-нибудь интересные идеи для решения проблемы с данными? Дайте нам знать!