Node.js'deki Büyük Verilerden Google Slaytlar sunuları oluşturun

1. Genel Bakış

Bu codelab'de, en yaygın yazılım lisanslarını analiz etmek için Google Slaytlar'ı özel bir sunu aracı olarak nasıl kullanabileceğinizi öğreneceksiniz. BigQuery API'yi kullanarak GitHub'daki tüm açık kaynak kodları sorgular ve sonuçlarınızı sunmak için Google Slaytlar API'yi kullanarak bir slayt gösterisi oluşturursunuz. Örnek uygulama Node.js kullanılarak oluşturulmuştur ancak aynı temel ilkeler her mimari için geçerlidir.

Neler öğreneceksiniz?

  • Slaytlar API'sini kullanarak sunum oluşturma
  • Büyük bir veri kümesinden analizler elde etmek için BigQuery'yi kullanma
  • Google Drive API'yi kullanarak dosya kopyalama

İhtiyacınız olanlar

  • Node.js yüklü
  • İnternete ve web tarayıcısına erişim
  • Google Hesabı
  • Google Cloud Platform projesi

2. Örnek kodu alın

Tüm örnek kodu bilgisayarınıza indirebilir veya...

...veya GitHub deposunu komut satırından kopyalayın.

git clone https://github.com/googleworkspace/slides-api.git

Depo, çalışan bir sürüme referans vermeniz gerekmesi ihtimaline karşı süreçteki her adımı temsil eden bir dizi dizin içerir.

start dizininde bulunan kopya üzerinde çalışırsınız ancak gerektiğinde diğer kopyaları referans olarak kullanabilir veya bu kopyalardan dosya kopyalayabilirsiniz.

3. Örnek uygulamayı çalıştırma

Öncelikle Node komut dosyasını çalıştıralım. İndirilen kodu kullanarak Node.js uygulamasını yüklemek ve başlatmak için aşağıdaki talimatları uygulayın:

  1. Bilgisayarınızda bir komut satırı terminali açın ve codelab'in start dizinine gidin.
  2. Node.js bağımlılarını yüklemek için aşağıdaki komutu girin.
npm install
  1. Komut dosyasını çalıştırmak için aşağıdaki komutu girin:
node .
  1. Bu projenin adımlarını gösteren karşılama mesajını inceleyin.
-- Start generating slides. --
TODO: Get Client Secrets
TODO: Authorize
TODO: Get Data from BigQuery
TODO: Create Slides
TODO: Open Slides
-- Finished generating slides. --

Yapılacaklar listemizi slides.js, license.js ve auth.js'de görebilirsiniz. Her adım önceki adımın tamamlanmasına bağlı olduğundan, uygulamayı tamamlamak için gereken adımları zincirlemek amacıyla JavaScript Promises'ı kullandığımızı unutmayın.

Söz konusu taahhütlere aşina değilseniz endişelenmeyin. İhtiyacınız olan tüm kodları sizin için sağlayacağız. Özetle, umutlar bize eşzamansız işlemeyi daha senkronize bir şekilde yönetmenin bir yolunu sunar.

4. İstemci Gizli Anahtarı Alma

Slaytlar, Bigquery ve Drive API'lerini kullanmak için bir OAuth istemcisi ve hizmet hesabı oluşturacağız.

Google Developers Console'u ayarlama

  1. Google Developers Console'da proje oluşturmak veya mevcut bir projeyi seçmek ve API'yi otomatik olarak etkinleştirmek için bu sihirbazı kullanın. Devam'ı, ardından Kimlik bilgilerine git'i tıklayın.
  2. Projenize kimlik bilgileri ekleyin sayfasında İptal düğmesini tıklayın.
  3. Sayfanın üst kısmından OAuth izin ekranı sekmesini seçin. Bir e-posta adresi seçin, ürün adını Slides API Codelab girin ve Kaydet düğmesini tıklayın.

BigQuery, Drive ve Slaytlar API'lerini etkinleştirme

  1. Kontrol paneli sekmesini seçin, API'yi etkinleştir düğmesini tıklayın ve aşağıdaki 3 API'yi etkinleştirin:
  2. BigQuery API
  3. Google Drive API
  4. Google Slides API

OAuth istemci gizli anahtarını indirme (Slaytlar ve Drive için)

  1. Kimlik bilgileri sekmesini seçin, Kimlik bilgileri oluştur düğmesini tıklayın ve OAuth istemci kimliği'ni seçin.
  2. Uygulama türünü Diğer olarak seçin, Google Slides API Codelab adını girin ve Oluştur düğmesini tıklayın.Açılan iletişim kutusunu kapatmak için Tamam'ı tıklayın.
  3. İstemci kimliğinin sağındaki file_download (JSON'u indir) düğmesini tıklayın.
  4. Gizli dosyanızı client_secret.json olarak yeniden adlandırın ve hem start/ hem de finish/ dizinlerine kopyalayın.

Hizmet Hesabı Gizli Anahtarını İndirme (BigQuery için)

  1. Kimlik bilgileri sekmesini seçin, Kimlik bilgileri oluştur düğmesini tıklayın ve Hizmet hesabı anahtarı'nı seçin.
  2. Açılır listeden Yeni Hizmet Hesabı'nı seçin. Hizmetiniz için Slides API Codelab Service adını seçin. Ardından Rol'ü tıklayın ve BigQuery'ye gidin ve hem BigQuery Veri Görüntüleyici hem de BigQuery İş Kullanıcısı'nı seçin.
  3. Anahtar türü olarak JSON'u seçin.
  4. Oluştur'u tıklayın. Anahtar dosyası, bilgisayarınıza otomatik olarak indirilir. Görüntülenen iletişim kutusundan çıkmak için Kapat'ı tıklayın.
  5. Gizli dosyanızı service_account_secret.json olarak yeniden adlandırın ve hem start/ hem de finish/ dizinlerine kopyalayın.

İstemci Gizli Anahtarı Alma

start/auth.js içinde getClientSecrets yöntemini dolduralım.

auth.js

const fs = require('fs');

/**
 * Loads client secrets from a local file.
 * @return {Promise} A promise to return the secrets.
 */
module.exports.getClientSecrets = () => {
  return new Promise((resolve, reject) => {
    fs.readFile('client_secret.json', (err, content) => {
      if (err) return reject('Error loading client secret file: ' + err);
      console.log('loaded secrets...');
      resolve(JSON.parse(content));
    });
  });
}

İstemci gizli anahtarları yüklendi. Kimlik bilgileri bir sonraki söze iletilir. Hata olmadığından emin olmak için projeyi node . ile çalıştırın.

5. OAuth2 İstemcisi Oluşturma

Slayt oluşturmak için auth.js dosyamıza aşağıdaki kodu ekleyerek Google API'lerine kimlik doğrulama özelliği ekleyelim. Bu kimlik doğrulama işlemi, Google Drive'daki dosyaları okumak ve yazmak, Google Slaytlar'da sunu oluşturmak ve Google BigQuery'den salt okuma sorguları yürütmek için Google Hesabınıza erişim isteğinde bulunur. (Not: getClientSecrets değerini değiştirmedik)

auth.js

const fs = require('fs');
const readline = require('readline');
const openurl = require('openurl');
const googleAuth = require('google-auth-library');
const TOKEN_DIR = (process.env.HOME || process.env.HOMEPATH ||
      process.env.USERPROFILE) + '/.credentials/';
const TOKEN_PATH = TOKEN_DIR + 'slides.googleapis.com-nodejs-quickstart.json';

// If modifying these scopes, delete your previously saved credentials
// at ~/.credentials/slides.googleapis.com-nodejs-quickstart.json
const SCOPES = [
  'https://www.googleapis.com/auth/presentations', // needed to create slides
  'https://www.googleapis.com/auth/drive', // read and write files
  'https://www.googleapis.com/auth/bigquery.readonly' // needed for bigquery
];

/**
 * Loads client secrets from a local file.
 * @return {Promise} A promise to return the secrets.
 */
module.exports.getClientSecrets = () => {
  return new Promise((resolve, reject) => {
    fs.readFile('client_secret.json', (err, content) => {
      if (err) return reject('Error loading client secret file: ' + err);
      console.log('loaded secrets...');
      resolve(JSON.parse(content));
    });
  });
}

/**
 * Create an OAuth2 client promise with the given credentials.
 * @param {Object} credentials The authorization client credentials.
 * @param {function} callback The callback for the authorized client.
 * @return {Promise} A promise to return the OAuth client.
 */
module.exports.authorize = (credentials) => {
  return new Promise((resolve, reject) => {
    console.log('authorizing...');
    const clientSecret = credentials.installed.client_secret;
    const clientId = credentials.installed.client_id;
    const redirectUrl = credentials.installed.redirect_uris[0];
    const auth = new googleAuth();
    const oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl);

    // Check if we have previously stored a token.
    fs.readFile(TOKEN_PATH, (err, token) => {
      if (err) {
        getNewToken(oauth2Client).then(() => {
          resolve(oauth2Client);
        });
      } else {
        oauth2Client.credentials = JSON.parse(token);
        resolve(oauth2Client);
      }
    });
  });
}

/**
 * Get and store new token after prompting for user authorization, and then
 * fulfills the promise. Modifies the `oauth2Client` object.
 * @param {google.auth.OAuth2} oauth2Client The OAuth2 client to get token for.
 * @return {Promise} A promise to modify the oauth2Client credentials.
 */
function getNewToken(oauth2Client) {
  console.log('getting new auth token...');
  openurl.open(oauth2Client.generateAuthUrl({
    access_type: 'offline',
    scope: SCOPES
  }));

  console.log(''); // \n
  return new Promise((resolve, reject) => {
    const rl = readline.createInterface({
      input: process.stdin,
      output: process.stdout
    });
    rl.question('Enter the code from that page here: ', (code) => {
      rl.close();
      oauth2Client.getToken(code, (err, token) => {
        if (err) return reject(err);
        oauth2Client.credentials = token;
        let storeTokenErr = storeToken(token);
        if (storeTokenErr) return reject(storeTokenErr);
        resolve();
      });
    });
  });
}

/**
 * Store token to disk be used in later program executions.
 * @param {Object} token The token to store to disk.
 * @return {Error?} Returns an error or undefined if there is no error.
 */
function storeToken(token) {
  try {
    fs.mkdirSync(TOKEN_DIR);
    fs.writeFileSync(TOKEN_PATH, JSON.stringify(token));
  } catch (err) {
    if (err.code != 'EEXIST') return err;
  }
  console.log('Token stored to ' + TOKEN_PATH);
}

6. BigQuery'yi ayarlama

BigQuery'yi keşfetme (İsteğe bağlı)

BigQuery, büyük veri kümelerini saniyeler içinde sorgulamamıza olanak tanır. Programlı olarak sorgulamadan önce web arayüzünü kullanalım. BigQuery'yi daha önce hiç ayarlamadıysanız bu hızlı başlangıçtaki adımları uygulayın.

BigQuery'de bulunan GitHub verilerine göz atmak ve kendi sorgularınızı çalıştırmak için Cloud Console'u açın. Bu sorguyu yazıp Çalıştır düğmesine basarak GitHub'daki en popüler yazılım lisanslarını öğrenelim.

bigquery.sql

WITH AllLicenses AS (
  SELECT * FROM `bigquery-public-data.github_repos.licenses`
)
SELECT
  license,
  COUNT(*) AS count,
  ROUND((COUNT(*) / (SELECT COUNT(*) FROM AllLicenses)) * 100, 2) AS percent
FROM `bigquery-public-data.github_repos.licenses`
GROUP BY license
ORDER BY count DESC
LIMIT 10

GitHub'daki milyonlarca herkese açık depoyu analiz ettik ve en popüler lisansları belirledik. Güzel! Şimdi aynı sorguyu bu kez programatik olarak çalıştırmayı ayarlayalım.

BigQuery'yi ayarlama

license.js dosyasındaki kodu değiştirin. bigquery.query işlevi bir promise döndürür.

license**.js**

const google = require('googleapis');
const read = require('read-file');
const BigQuery = require('@google-cloud/bigquery');
const bigquery = BigQuery({
  credentials: require('./service_account_secret.json')
});

// See codelab for other queries.
const query = `
WITH AllLicenses AS (
  SELECT * FROM \`bigquery-public-data.github_repos.licenses\`
)
SELECT
  license,
  COUNT(*) AS count,
  ROUND((COUNT(*) / (SELECT COUNT(*) FROM AllLicenses)) * 100, 2) AS percent
FROM \`bigquery-public-data.github_repos.licenses\`
GROUP BY license
ORDER BY count DESC
LIMIT 10
`;

/**
 * Get the license data from BigQuery and our license data.
 * @return {Promise} A promise to return an object of licenses keyed by name.
 */
module.exports.getLicenseData = (auth) => {
  console.log('querying BigQuery...');
  return bigquery.query({
    query,
    useLegacySql: false,
    useQueryCache: true,
  }).then(bqData => Promise.all(bqData[0].map(getLicenseText)))
    .then(licenseData => new Promise((resolve, reject) => {
      resolve([auth, licenseData]);
    }))
    .catch((err) => console.error('BigQuery error:', err));
}

/**
 * Gets a promise to get the license text about a license
 * @param {object} licenseDatum An object with the license's
 *   `license`, `count`, and `percent`
 * @return {Promise} A promise to return license data with license text.
 */
function getLicenseText(licenseDatum) {
  const licenseName = licenseDatum.license;
  return new Promise((resolve, reject) => {
    read(`licenses/${licenseName}.txt`, 'utf8', (err, buffer) => {
      if (err) return reject(err);
      resolve({
        licenseName,
        count: licenseDatum.count,
        percent: licenseDatum.percent,
        license: buffer.substring(0, 1200) // first 1200 characters
      });
    });
  });
}

Nesnelerimizin yapısını anlamak ve kodun işleyişini görmek için Promise'ın geri çağırma işlevindeki bazı verileri console.log deneyebilirsiniz.

7. Slayt Oluşturma

Şimdi eğlenceli kısıma geçelim. Slaytlar API'sinin create ve batchUpdate yöntemlerini çağırarak slayt oluşturalım. Dosyamız aşağıdakiyle değiştirilmelidir:

slides.js

const google = require('googleapis');
const slides = google.slides('v1');
const drive = google.drive('v3');
const openurl = require('openurl');
const commaNumber = require('comma-number');

const SLIDE_TITLE_TEXT = 'Open Source Licenses Analysis';

/**
 * Get a single slide json request
 * @param {object} licenseData data about the license
 * @param {object} index the slide index
 * @return {object} The json for the Slides API
 * @example licenseData: {
 *            "licenseName": "mit",
 *            "percent": "12.5",
 *            "count": "1667029"
 *            license:"<body>"
 *          }
 * @example index: 3
 */
function createSlideJSON(licenseData, index) {
  // Then update the slides.
  const ID_TITLE_SLIDE = 'id_title_slide';
  const ID_TITLE_SLIDE_TITLE = 'id_title_slide_title';
  const ID_TITLE_SLIDE_BODY = 'id_title_slide_body';

  return [{
    // Creates a "TITLE_AND_BODY" slide with objectId references
    createSlide: {
      objectId: `${ID_TITLE_SLIDE}_${index}`,
      slideLayoutReference: {
        predefinedLayout: 'TITLE_AND_BODY'
      },
      placeholderIdMappings: [{
        layoutPlaceholder: {
          type: 'TITLE'
        },
        objectId: `${ID_TITLE_SLIDE_TITLE}_${index}`
      }, {
        layoutPlaceholder: {
          type: 'BODY'
        },
        objectId: `${ID_TITLE_SLIDE_BODY}_${index}`
      }]
    }
  }, {
    // Inserts the license name, percent, and count in the title
    insertText: {
      objectId: `${ID_TITLE_SLIDE_TITLE}_${index}`,
      text: `#${index + 1} ${licenseData.licenseName}  — ~${licenseData.percent}% (${commaNumber(licenseData.count)} repos)`
    }
  }, {
    // Inserts the license in the text body paragraph
    insertText: {
      objectId: `${ID_TITLE_SLIDE_BODY}_${index}`,
      text: licenseData.license
    }
  }, {
    // Formats the slide paragraph's font
    updateParagraphStyle: {
      objectId: `${ID_TITLE_SLIDE_BODY}_${index}`,
      fields: '*',
      style: {
        lineSpacing: 10,
        spaceAbove: {magnitude: 0, unit: 'PT'},
        spaceBelow: {magnitude: 0, unit: 'PT'},
      }
    }
  }, {
    // Formats the slide text style
    updateTextStyle: {
      objectId: `${ID_TITLE_SLIDE_BODY}_${index}`,
      style: {
        bold: true,
        italic: true,
        fontSize: {
          magnitude: 10,
          unit: 'PT'
        }
      },
      fields: '*',
    }
  }];
}

/**
 * Creates slides for our presentation.
 * @param {authAndGHData} An array with our Auth object and the GitHub data.
 * @return {Promise} A promise to return a new presentation.
 * @see https://developers.google.com/apis-explorer/#p/slides/v1/
 */
module.exports.createSlides = (authAndGHData) => new Promise((resolve, reject) => {
  console.log('creating slides...');
  const [auth, ghData] = authAndGHData;

  // First copy the template slide from drive.
  drive.files.copy({
    auth: auth,
    fileId: '1toV2zL0PrXJOfFJU-NYDKbPx9W0C4I-I8iT85TS0fik',
    fields: 'id,name,webViewLink',
    resource: {
      name: SLIDE_TITLE_TEXT
    }
  }, (err, presentation) => {
    if (err) return reject(err);

    const allSlides = ghData.map((data, index) => createSlideJSON(data, index));
    slideRequests = [].concat.apply([], allSlides); // flatten the slide requests
    slideRequests.push({
      replaceAllText: {
        replaceText: SLIDE_TITLE_TEXT,
        containsText: { text: '{{TITLE}}' }
      }
    })

    // Execute the requests
    slides.presentations.batchUpdate({
      auth: auth,
      presentationId: presentation.id,
      resource: {
        requests: slideRequests
      }
    }, (err, res) => {
      if (err) {
        reject(err);
      } else {
        resolve(presentation);
      }
    });
  });
});

8. Slaytlar'ı aç

Son olarak, sunuyu tarayıcıda açalım. slides.js'te aşağıdaki yöntemi güncelleyin.

slides.js

/**
 * Opens a presentation in a browser.
 * @param {String} presentation The presentation object.
 */
module.exports.openSlidesInBrowser = (presentation) => {
  console.log('Presentation URL:', presentation.webViewLink);
  openurl.open(presentation.webViewLink);
}

Nihai sonucu göstermek için projenizi son bir kez çalıştırın.

9. Tebrikler!

BigQuery kullanılarak analiz edilen verilerden başarıyla Google Slaytlar oluşturdunuz. Komut dosyanız, en yaygın yazılım lisanslarının analizini bildirmek için Google Slaytlar API'yi ve BigQuery'yi kullanarak bir sunu oluşturur.

Olası iyileştirmeler

Daha da ilgi çekici bir entegrasyon oluşturmak için aşağıdaki ek fikirlerden yararlanabilirsiniz:

  • Her slayta resim ekleme
  • Gmail API'yi kullanarak slaytlarınızı e-posta ile paylaşma
  • Şablon slaytını komut satırı bağımsız değişkeni olarak özelleştirme

Daha Fazla Bilgi