Dışa Veri Aktarma API'sından CSV Biçimine Veri Çıkışı

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


Giriş

Bu makalede, herhangi bir sorgudan 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 elde edilen Analytics verileriyle gerçekleştirdiği en yaygın görevlerden biridir. Bu nedenle, süreci otomatikleştirmek, düzenli olarak çok zaman tasarrufu yapmanın kolay bir yoludur. Ayrıca, sorgulardan CSV dokümanlarını yazdırmak için bir kod oluşturduğunuzda, bu kodu yazdığınız özel gösterge tabloları için otomatik rapor oluşturucular, postalar ve "dışa aktarma" işlevleri gibi daha büyük projelere entegre edebilirsiniz.

Başlamadan Önce

Aşağıdakilere sahipseniz bu makaleden en iyi şekilde yararlanacaksınız:

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

Programa genel bakış

Bu makalede ele alınan kod şunları yapacaktır:

  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. Her DataEntry, sonuçta elde edilen çıkışta bir satır oluşturur.
    • Her bir değeri, CSV açısından güvenli çıkışlar için bir temizleme yöntemiyle çalıştırın.
  3. Tüm girişlerin CSV-Güvenli olmasını sağlayan bir "Temizleyici" yöntemi yazın.
  4. Herhangi bir Data Export API sorgusunu alıp bir CSV dosyasına dönüştürebilecek bir Java sınıfı sağlayın.

Başa Dön

Yapılandırılabilir Çıkış Akışlarına izin 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. Böylece sınıfınızı kullanan herhangi bir kod, çıkışın standart dışı mı yoksa doğrudan dosyaya mı gideceğine karar verebilir. Burada tek yapmanız gereken bir PrintStream nesnesi için getter/setter yöntemini ayarlamaktır. Bu, sınıf tarafından yapılan tüm baskıları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. Bir kullanıcı, bu dosyayla ilgili bir PrintStream nesnesi oluşturmak için yalnızca dosya adına ihtiyaç duyar.

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

Başa Dön

Verileri yineleme

CSV dosyasının ilk satırı sütun adları satırıdı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ç hepsinden sonra virgülleri yazdırın.

Aşağıda, satır başlıklarını yazdırma yönteminden biri gösterilmektedir. 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 "body" kısmının (sütun adları satırının altındaki her şey) yazdırılması oldukça benzerdir. Arada iki temel fark vardır. İlk olarak, değerlendirilen yalnızca ilk giriş değildir. Kodun, feed nesnesindeki tüm girişler arasında döngüye girmesi gerekir. İkinci olarak, temizlenecek ve yazdırılacak değeri çekmek için getName() yöntemini kullanmak yerine getValue() 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şler ve girişlerinizi çıktı olarak 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ğer virgül içeriyorsa ne olur? Bu değerler temizlenmelidir.

Başa Dön

Verileri CSV Uyumluluğu İçin Ayıklama

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 işlem yapmayı kolaylaştırır. Değeriniz virgül içeriyorsa ne olur? Değerlerinizden birinde satır sonu 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 bir çift tırnak karakteri içeriyorsa ikinci bir çift tırnak karakteriyle kod dışına alın.
  • Dizede virgül varsa tüm dizeyi çift tırnak içine alın (bunu yapmadıysanız).
  • Dizede satır sonu varsa tüm dizeyi çift tırnak içine alın (bunu yapmadıysanız).
  • Dize herhangi bir türde boşlukla başlıyorsa veya bitiyorsa tüm dizeyi çift tırnak içine alın (önceden yapmadıysanız).

Bu noktada değerlerinizin nasıl görünmesi gerektiğini görselleştirmek biraz zor olabilir. Bu nedenle bazı örnekleri burada bulabilirsiniz. Her örneğin tek bir değeri temsil ettiğini ve bu şekilde kod dışı bırakı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ülle,ayrılmış "virgül,ayrılmış"
İki
satır
"İki
satır"
_ lineer boşluk ve bir virgül "_frontend boşluk ve bir 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ı halletmenin en kolay yolu, temizleme yöntemi yazmaktır. Şüpheli veriler devreye girer ve temiz, düzgün CSV değerleri ortaya çıkar. Burada, tam da böyle bir yöntemin iyi bir uygulama örneği verilmiştir.

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();
}

Bu yöntem ilk olarak mevcut çift tırnakların olup olmadığını kontrol eder. Bu, bir dizenin çift tırnak kullanılarak sarmalanmasını içerdiği için diğer tüm kontrollerden önce yapılmalıdır. Burada, değerin parçası olan çift tırnak ve daha önce bu yöntemle eklenen çift tırnak arasındaki farkın belirlenmesi can sıkıcı olabilir. Bunlardan kolayca kaçabilirler, yalnızca iki katına çıkarılmaları gerekir. Her " bir "", her "" ise """" olur.

Bu koşul karşılandıktan sonra, diğer tüm koşullar (eksiklenmemiş 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 kodun bir StringBuilder nesnesi kullandığını, hiçbir zaman ham dizeyi doğrudan değiştirmediğini unutmayın. Bunun nedeni, StringBuilder özelliğinin bellekte geçici kopyalar oluşturmadan dizeyi serbest bir şekilde değiştirmenize izin vermesidir. Java'daki dizeler sabit olduğu için yaptığınız her küçük ayar yepyeni bir dize oluşturur. Elektronik tablo verilerinde gezinirken bu durum çok hızlı bir şekilde bir araya gelebilir.

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

Başa Dön

Sırada Ne Var?

Size altın bir çekiç verildiğine göre artık tırnak avına gitmeniz çok doğal. Başlamanıza yardımcı olacak bazı fikirler:

  • Örnek sorguyu temel alan bir CSV dosyası yazdırmak için bu sınıfı kullanan örnek uygulama kaynak koduna göz atın. Çıkış dosya adını komut satırı parametresi olarak alır ve varsayılan olarak standart olarak yazdırır. Bunu başlangıç noktası olarak kullanın, mükemmel bir şey geliştirin!
  • 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, 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.