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

1. Genel Bakış

Bu codelab'de, Google Slaytlar'ı en yaygın yazılım lisanslarının analizi için özel sunum aracı olarak nasıl kullanabileceğinizi öğreneceksiniz. BigQuery API'yi kullanarak GitHub'daki tüm açık kaynak kodlarını sorgulayacak ve sonuçlarınızı sunmak için Google Slaytlar API'yi kullanarak bir slayt kümesi oluşturacaksınız. Örnek uygulama Node.js kullanılarak oluşturulur, ancak aynı temel ilkeler tüm mimariler için de geçerlidir.

Neler öğreneceksiniz?

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

Gerekenler

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

2. Örnek kodu alın

Tüm örnek kodu bilgisayarınıza indirebilirsiniz...

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

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

Depo, çalışan bir sürüme referans vermeniz gerekirse süreç boyunca her adımı temsil eden bir dizin grubu içerir.

start dizininde bulunan kopya üzerinde çalışırsınız, ancak gerektiğinde diğerlerine başvurabilir veya diğerlerindeki dosyaları kopyalayabilirsiniz.

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

Öncelikle Node komut dosyasını çalıştıralım. Kod indirildikten sonra, 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ılıkları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 selamlamayı düşünün.
-- Start generating slides. --
TODO: Get Client Secrets
TODO: Authorize
TODO: Get Data from BigQuery
TODO: Create Slides
TODO: Open Slides
-- Finished generating slides. --

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

Sözler hakkında bilginiz yoksa endişelenmeyin. Size ihtiyacınız olan tüm kodu vereceğiz. Kısacası, vaatler bize eşzamansız işlemeyi daha eşzamanlı bir şekilde yönetme olanağı sunuyor.

4. İstemci Gizli Anahtarları Alma

Slaytlar, BigQuery ve Drive API'lerini kullanmak için OAuth İstemcisi ve Hizmet Hesabı oluşturacağız.

Google Developers Console'u kurun

  1. Google Developers Console'da proje oluşturmak veya 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ında OAuth izin ekranı sekmesini seçin. Bir E-posta adresi seçin, Ürün adı Slides API Codelab girin ve Kaydet düğmesini tıklayın.

BigQuery, Drive ve Slaytlar API'lerini etkinleştirme

  1. Dashboard (Kontrol Paneli) sekmesini seçin, Enable API (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'si
  4. Google Slaytlar API'si

OAuth İstemci Sırrını İndir (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. Diğer uygulama türünü 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 (Download JSON) düğmesini tıklayın.
  4. Gizli anahtar dosyanızı client_secret.json olarak yeniden adlandırın ve hem start/ hem de finish/ dizinine kopyalayın.

Hizmet Hesabı Gizli Anahtarını İndir (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 listede New Service Account (Yeni Hizmet Hesabı) seçeneğini belirleyin. Hizmetiniz için Slides API Codelab Service adını seçin. Ardından Rol'ü tıklayın, BigQuery'ye ilerleyin ve hem BigQuery Veri Görüntüleyicisi hem de BigQuery İş Kullanıcısı'nı seçin.
  3. Anahtar türü olarak JSON'yi seçin.
  4. Oluştur'u tıklayın. Anahtar dosyası otomatik olarak bilgisayarınıza indirilir. Açılan iletişim kutusundan çıkmak için Kapat'ı tıklayın.
  5. Gizli anahtar dosyanızı service_account_secret.json olarak yeniden adlandırın ve hem start/ hem de finish/ dizinine kopyalayın.

İstemci Gizli Anahtarları Alma

start/auth.js uygulamasında 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 vadeye aktarılacaktır. 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 ekleyelim. Bu kimlik doğrulama işlemi; Google Drive'da dosya okuma ve yazma, Google Slaytlar'da sunu oluşturma ve Google BigQuery'den salt okunur sorgular yürütme işlemleri için Google Hesabınıza erişim isteğinde bulunur. (Not: getClientSecrets öğesini 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 kurun

BigQuery'yi keşfedin (isteğe bağlı)

BigQuery, çok büyük veri kümelerini saniyeler içinde sorgulamamızı sağlıyor. Programatik sorgu yapmadan önce web arayüzünü kullanalım. Daha önce BigQuery'yi kurmadıysanız bu hızlı başlangıç kılavuzundaki adımları uygulayın.

Cloud Console'u açarak BigQuery'de kullanılabilen GitHub verilerine göz atabilir ve kendi sorgularınızı çalıştırabilirsiniz. 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ı bulduk. Güzel! Şimdi aynı sorguyu bu kez programatik olarak çalıştırmayı deneyelim.

BigQuery'yi kurun

license.js dosyasındaki kodu değiştirin. bigquery.query işlevi bir söz 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ş başında olduğunu görmek için Promise'ın geri çağırma yöntemindeki verilerin bir kısmını console.log deneyin.

7. Slayt Oluşturma

Şimdi sıra eğlenceli kısma geldi! Slaytlar API'sinin create ve batchUpdate yöntemlerini çağırarak slayt oluşturalım. Dosyamız şununla 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 ürününde 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 ile analiz edilen verilerden başarıyla Google Slaytlar oluşturdunuz. Komut dosyanız, Google Slaytlar API ve BigQuery'yi kullanarak en yaygın yazılım lisanslarının analizini bildiren bir sunu oluşturur.

Olası İyileştirmeler

Aşağıda, daha da etkileyici bir entegrasyon oluşturmaya yönelik bazı ek fikirler belirtilmiştir:

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

Daha Fazla Bilgi