Data Export API'den CSV Biçimine Veri Çıkışı Oluşturma

Alexander Lucas, Google Analytics API Ekibi – Ağustos 2010


Giriş

Bu makalede, tüm sorgulardan Google Analytics Data Export API'ye nasıl veri aktarılacağı ve sonuçları popüler CSV biçiminde nasıl çıkarılacağı gösterilmektedir. Bu, kullanıcıların Data Export API'den alınan Analytics verileriyle en sık gerçekleştirdiği görevlerden biridir. Bu nedenle, süreci otomatik hale getirmek düzenli olarak çok zaman tasarrufu sağlamanın kolay bir yoludur. Ayrıca, sorgulardan CSV belgelerini yazdırmak için bir kod edindikten sonra, bu kodu yazdığınız özel gösterge tabloları için otomatik rapor oluşturucular, postalayıcılar ve "dışa aktarma" işlevleri gibi daha büyük projelere entegre edebilirsiniz.

Başlamadan Önce

Aşağıdakileri sağlıyorsanız bu makaleden en iyi şekilde yararlanabilirsiniz:

  • Java ile çalışma bilgisi.
  • Boyutlar ve metrikler hakkında bilgi de dahil olmak üzere Google Analytics ile ilgili çalışma bilgisi.
  • Gerçek verileri içeren etkin bir Google Analytics hesabına erişim.
  • Data Export API Java Başlangıç Kılavuzu hakkında bilgi sahibi olun. Bu makalede, bu kılavuzda ele alınan her şeyi zaten bildiğiniz varsayılmaktadır.
  • Kaynak kodun tamamını içeren ve AnalyticsCvsPrinter.java adresinden edinebileceğiniz bir yerel kopya. Bu kodu kullanan örnek bir uygulamayı AnalyticsCsvDemo.java adresinde bulabilirsiniz.

Programa genel bakış

Bu makalede ele alınan kod şunları yapar:

  1. Çalışma zamanında kodun konsola mı yoksa bir dosya akışına mı yazdırılacağını seçmeyi etkinleştirin.
  2. Parametre olarak bir DataFeed nesnesi verildiğinde verileri CSV biçiminde yazdırın:
    • Satır başlıklarını yazdır.
    • Veri satırlarını yazdırın. Burada her DataEntry, sonuçta bir satır oluşturur.
    • Her değeri, CSV'de güvenli çıkış için bir temizleme yöntemiyle çalıştırın.
  3. Tüm girişi CSV-Güvenli hale getiren bir "Temizleyici" yöntemi yazın.
  4. Tüm Data Export API sorgularını alıp CSV dosyasına dönüştürebilen bir Java sınıfı sağlayın.

Başa Dön

Yapılandırılabilir Çıkış Akışlarına İzin Ver

Yapmanız gereken ilk şey, sınıfınızın yazdırma işlemi yapması için yapılandırılabilir bir çıkış akışı oluşturmaktır. Bu şekilde, sınıfınızı kullanan herhangi bir kod, çıkışın standart dışı mı yoksa doğrudan bir dosyaya mı gideceğine karar verebilir. Burada tek yapmanız gereken bir PrintStream nesnesi için getter/setter yöntemi ayarlamaktır. Bu, sınıf tarafından yapılan tüm yazdırmaların hedefi olacaktır.

private PrintStream printStream = System.out;

public PrintStream getPrintStream() {
  return printStream;
}

public void setPrintStream(PrintStream printStream) {
  this.printStream = printStream;
}

Çıkışı bir dosyaya ayarlamak da çok kolaydır. Söz konusu dosya için PrintStream nesnesi oluşturmak için yalnızca dosya adına ihtiyaç duyulur.

FileOutputStream fstream = new FileOutputStream(filename);
PrintStream stream = new PrintStream(fstream);
csvprinter.setPrintStream(stream);

Başa Dön

Verileri tekrarlama

CSV dosyasının ilk satırı, sütun adlarının bulunduğu satırdır. Her sütun, veri feed'indeki bir boyutu veya metriği temsil eder. Bu nedenle, bu ilk satırı yazdırmak için aşağıdakileri yapın.

  1. Feed'deki ilk girişi alın.
  2. Bu girişin getDimensions yöntemini kullanarak bir boyut listesini yineleyin.
  3. Dimension.getName() yöntemini ve ardından virgül kullanarak her boyutun adını yazdırın.
  4. Aynı şeyi getMetrics() yöntemini kullanarak metrikler için de yapın. Son metrik hariç her şeyden sonra virgülleri yazdırın.

Aşağıda, satır başlıklarını yazdırma yönteminin bir uygulaması verilmiştir. Bu kodun, tüm satırı temsil eden bir dize döndürmediğini unutmayın. Değerleri işlerken bir çıkış akışına yazdırır.

public void printRowHeaders(DataFeed feed) {
    if(feed.getEntries().size() == 0) {
      return;
    }

    DataEntry firstEntry = feed.getEntries().get(0);

    Iterator<Dimension> dimensions = firstEntry.getDimensions().iterator();
    while (dimensions.hasNext()) {
      printStream.print(sanitizeForCsv(dimensions.next().getName()));
      printStream.print(",");
    }

    Iterator<Metric> metrics = firstEntry.getMetrics().iterator();
    while (metrics.hasNext()) {
      printStream.print(sanitizeForCsv(metrics.next().getName()));
      if (metrics.hasNext()) {
        printStream.print(",");
      }
    }
    printStream.println();
  }

CSV dosyasının "gövdesini" (sütun adı satırının altındaki her şey) yazdırmak çok benzerdir. Yalnızca iki temel fark vardır. Öncelikle, değerlendirilen ilk girişle sınırlı kalmıyoruz. Kodun, feed nesnesindeki tüm girişleri döngüye alması gerekir. İkinci olarak, temizlenecek ve yazdırılacak değeri çekmek için getName() yöntemini kullanmak yerine getValue() politikasını kullanın.

public void printBody(DataFeed feed) {
    if(feed.getEntries().size() == 0) {
      return;
    }

    for (DataEntry entry : feed.getEntries()) {
      printEntry(entry);
    }
  }

  public void printEntry(DataEntry entry) {
    Iterator<Dimension> dimensions = entry.getDimensions().iterator();
    while (dimensions.hasNext()) {
      printStream.print(sanitizeForCsv(dimensions.next().getValue()));
      printStream.print(",");
    }

    Iterator<Metric> metrics = entry.getMetrics().iterator();
    while (metrics.hasNext()) {
      printStream.print(sanitizeForCsv(metrics.next().getValue()));
      if (metrics.hasNext()) {
        printStream.print(",");
      }
    }
    printStream.println();
  }

Bu kod, feed'inizi girişlere ve girişlerinizi çıktısı için yazdırılacak değerlere ayırır. Peki bu değerleri nasıl CSV uyumlu hale getirebiliriz? "Virgülle ayrılmış değerler" dosyasındaki bir değerde virgül varsa ne olur? Bu değerlerin temizlenmesi gerekir.

Başa Dön

CSV Uyumluluğu İçin Verileri Temizleme

CSV basit bir biçimdir. CSV dosyası bir veri tablosunu temsil eder ve her satır bu tablodaki bir satırı temsil eder. Bu satırdaki değerler virgülle ayrılır. Yeni satır, yeni bir veri satırı anlamına gelir.

Ne yazık ki, bu basit biçim, kötü verilerle ilgili yanıltıcı bir şekilde işleri çöpe atmayı kolaylaştırıyor. Değeriniz virgül içeriyorsa ne olur? Değerlerinizden birinin içinde satır sonları varsa ne olur? Virgül ve değerler arasındaki boşlukta ne olması gerekir? Tüm bu durumlar birkaç basit kural kullanılarak açıklanabilir.

  • Dize, çift tırnak karakteri içeriyorsa ikinci bir çift tırnak karakteriyle çıkış yapın.
  • Dizede virgül varsa tüm dizeyi çift tırnak içine alın (önceden yapmadıysanız).
  • Dizede satır sonu varsa tüm dizeyi çift tırnak içine alın (önceden yapmadıysanız).
  • Dize herhangi bir boşlukla başlıyorsa veya bitiyorsa tüm dizeyi çift tırnak içine alın (halihazırda yoksa).

Bu noktada değerlerinizin nasıl görünmesi gerektiğini görselleştirmek biraz zor olabilir. Bu nedenle, aşağıda bazı örnekler verilmiştir. Her örneğin tek bir değeri temsil ettiğini ve bu şekilde çıkış yapıldığını unutmayın. Anlaşılır olması için boşluklar _ karakteriyle gösterilir.

Önce Sonra
değişmedi değişmedi
rastgele " çift tırnak rastgele "" çift tırnak
virgül,ayrılmış "virgül,ayrılmış"
İki
satır
"İki
satır"
_Lead boşluk ve virgül "_ öngörme boşluk ve virgül"
"baştaki alıntı, virgül """baştaki tırnak işareti, virgül"
_boşluk, virgül
ikinci satır ve çift tırnak"
"_boşluk, virgül
ikinci satır ve çift tırnak"""

Tüm bu koşulları karşılamanın en kolay yolu, temizleme yöntemi yazmaktır. Şüpheli veriler devreye girer ve temiz, temiz CSV değerleri ortaya çıkar. İşte böyle bir yöntemin iyi bir uygulama örneği.

private String sanitizeForCsv(String cellData) {
  StringBuilder resultBuilder = new StringBuilder(cellData);

  // Look for doublequotes, escape as necessary.
  int lastIndex = 0;
  while (resultBuilder.indexOf("\"", lastIndex) >= 0) {
    int quoteIndex = resultBuilder.indexOf("\"", lastIndex);
    resultBuilder.replace(quoteIndex, quoteIndex + 1, "\"\"");
    lastIndex = quoteIndex + 2;
  }

  char firstChar = cellData.charAt(0);
  char lastChar = cellData.charAt(cellData.length() - 1);

  if (cellData.contains(",") || // Check for commas
      cellData.contains("\n") ||  // Check for line breaks
      Character.isWhitespace(firstChar) || // Check for leading whitespace.
      Character.isWhitespace(lastChar)) { // Check for trailing whitespace
      resultBuilder.insert(0, "\"").append("\""); // Wrap in doublequotes.
  }
    return resultBuilder.toString();
}

Yöntem, mevcut çift tırnak olup olmadığını kontrol ederek başlar. Bu, bir dizenin çift tırnak işaretiyle sarmalanması içerdiğinden diğer tüm kontrollerden önce yapılmalıdır. Değerin parçası olan çift tırnaklar ile daha önce bu yöntemle eklenen çift tırnak işaretleri arasındaki farkın tespit edilmesi rahatsız edici olabilir. Bunlar kolayca kaçabilir; yalnızca ikiye katlanmaları gerekir. Her " bir "", her "" olarak bir """" olur.

Bu koşul karşılandıktan sonra, diğer tüm koşullar (kısaltılmamış boşluklar, virgüller ve satır sonları) kontrol edilebilir. Bunlardan herhangi biri varsa değeri çift tırnak içine almanız yeterlidir.

Yukarıdaki komutun bir StringBuilder nesnesi kullandığını, hiçbir zaman ham dizeyi doğrudan etkilemediğini unutmayın. Bunun nedeni, StringBuilder özelliğinin bellekte ara kopyalar oluşturmadan dizeyi serbest bir şekilde değiştirmenize olanak tanımasıdır. Java'daki dizeler sabit olduğundan, yaptığınız her küçük ayarlama yepyeni bir dize oluşturur. Elektronik tablo verilerinde gezinirken bu veriler bir çırpıda toplanabilir.

Satır sayısı x Satır başına değer sayısı x Değerdeki değişiklikler = Oluşturulan Toplam Yeni Dize Sayısı
10.000 10 3 300.000

Başa Dön

Sırada Ne Var?

Artık size altın bir çekiç verildiğine göre, çivi avına çıkmanız çok doğal. Başlamanıza yardımcı olacak bazı fikirler.

  • Örnek bir sorgudan CSV dosyası yazdırmak için bu sınıfı kullanan örnek uygulama kaynak koduna göz atın. Komut satırı parametresi olarak bir çıkış dosya adı alır ve varsayılan olarak standart modda yazdırır. Bunu başlangıç noktası olarak kullanın, mükemmel bir şey oluşturun!
  • CSV birçok popüler biçimden yalnızca biridir. Sınıfı TSV, YAML, JSON veya XML gibi farklı bir biçimde olacak şekilde düzenleyin.
  • CSV'ler oluşturan ve tamamlandığında bunları e-postayla gönderen bir uygulama yazın. Kolay ve otomatik aylık raporlama!
  • Verilerinizi ayrıntılı olarak incelemenizi sağlayacak güçlü bir arayüz için sorguları etkileşimli olarak girmenizi sağlayan bir uygulama yazın.