1. مقدمة
في هذا الدرس التطبيقي حول الترميز، ستتعرّف على كيفية الاستفادة من إمكانات Apache Spark لتحويل البيانات ضمن واجهة BigQuery Studio المألوفة. ستقرأ البيانات من BigQuery، وتجري عملية تنظيف البيانات وتحويلها باستخدام PySpark، وتكتب النتائج مرة أخرى في جدول BigQuery جديد، وكل ذلك من دفتر ملاحظات واحد.
خلال هذا الدرس العملي، ستتّبع نهجًا خطوة بخطوة على النحو التالي:
- إعداد مشروعك على Google Cloud وتفعيل جميع واجهات برمجة التطبيقات المطلوبة فيه
- إنشاء حزمة GCS للمجلد المؤقت
- استيراد المكتبات المطلوبة لتشغيل Apache Spark
- تهيئة جلسة Spark باستخدام موصّل BigQuery
- قراءة عيّنة بيانات "إحصاءات Google" من مجموعة بيانات BigQuery العامة
- تحويل البيانات باستخدام البيانات المجمّعة حسب متصفّح الجهاز (المقاييس الأساسية)
- تحويل البيانات باستخدام "تحليل مصادر الزيارات" مع احتساب الإيرادات
- تحويل البيانات باستخدام "التحليل الجغرافي"
- كتابة البيانات بعد تحويلها إلى جدول BigQuery
نظرة عامة على البنية

المتطلبات الأساسية
- مشروع على Google Cloud Platform (GCP) تم تفعيل الفوترة فيه
- يجب تفعيل واجهة BigQuery API وواجهة BigQuery Connection API في مشروعك على Google Cloud Platform.
- معرفة أساسية بلغة SQL وPython
ما ستتعلمه
- كيفية استخراج البيانات باستخدام Apache Spark في "أوراق ملاحظات BigQuery Studio"
- كيفية تحويل البيانات أو تجميعها باستخدام Apache Spark في "أوراق ملاحظات BigQuery Studio"
- كيفية كتابة البيانات بعد تحويلها أو تجميعها باستخدام Apache Spark في "أوراق ملاحظات BigQuery Studio"
المتطلبات
- متصفّح الويب Chrome
- حساب Gmail
- مشروع على السحابة الإلكترونية تم تفعيل الفوترة فيه
2. الإعداد الأساسي والمتطلبات
إعداد بيئة الاختبار الذاتي
- سجِّل الدخول إلى Google Cloud Console وأنشِئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب.



- اسم المشروع هو الاسم المعروض للمشاركين في هذا المشروع. وهي سلسلة أحرف لا تستخدمها Google APIs. ويمكنك تعديلها في أي وقت.
- رقم تعريف المشروع فريد في جميع مشاريع Google Cloud ولا يمكن تغييره بعد ضبطه. تنشئ Cloud Console سلسلة فريدة تلقائيًا، ولا يهمّك عادةً ما هي. في معظم دروس البرمجة، عليك الرجوع إلى رقم تعريف مشروعك (يُشار إليه عادةً باسم
PROJECT_ID). إذا لم يعجبك رقم التعريف الذي تم إنشاؤه، يمكنك إنشاء رقم آخر عشوائي. يمكنك بدلاً من ذلك تجربة اسم مستخدم من اختيارك ومعرفة ما إذا كان متاحًا. لا يمكن تغيير هذا الخيار بعد هذه الخطوة ويظل ساريًا طوال مدة المشروع. - للعلم، هناك قيمة ثالثة، وهي رقم المشروع، تستخدمها بعض واجهات برمجة التطبيقات. يمكنك الاطّلاع على مزيد من المعلومات حول هذه القيم الثلاث في المستندات.
- بعد ذلك، عليك تفعيل الفوترة في Cloud Console لاستخدام موارد/واجهات برمجة تطبيقات Cloud. لن تكلفك تجربة هذا الدرس البرمجي الكثير، إن وُجدت أي تكلفة. لإيقاف الموارد وتجنُّب تحمّل تكاليف فوترة تتجاوز هذا البرنامج التعليمي، يمكنك حذف الموارد التي أنشأتها أو حذف المشروع. يمكن لمستخدمي Google Cloud الجدد الاستفادة من برنامج الفترة التجريبية المجانية بقيمة 300 دولار أمريكي.
3- قبل البدء
تفعيل واجهة برمجة التطبيقات
قبل استخدام "أوراق ملاحظات BigQuery Studio"، يجب تفعيل واجهات برمجة التطبيقات التالية:
- واجهة برمجة التطبيقات Compute Engine API
- Dataform API
- Vertex AI API
للتفعيل يدويًا، انتقِل إلى BigQuery. في شريط علامات التبويب في جزء المحرّر، انقر على القائمة المنسدلة للسهم بجانب علامة +، وأبقِ المؤشر فوق دفتر ملاحظات، ثم اختَر نموذج BigQuery أو دفتر ملاحظات فارغ أو نموذج Spark.

في النافذة Enable Core feature API، انقر على Enable في BigQuery Unified API.

بعد الانتهاء، فعِّل الخيار ثم انقر على "إغلاق". يُرجى الرجوع إلى مقالة تفعيل BigQuery Studio لإدارة مواد العرض لمزيد من التفاصيل.
4. قراءة مجموعة بيانات عامة
أولاً، سننشئ حزمة GCS للاستخدام المؤقت حتى نتمكّن من تشغيل Spark في "دفاتر ملاحظات BigQuery Studio".
- في Google Cloud Console، انتقِل إلى BigQuery
- في شريط علامات التبويب في جزء المحرّر، انقر على السهم المنسدل بجانب علامة +، ثم مرِّر المؤشر فوق دفتر الملاحظات، ثم اختَر دفتر ملاحظات فارغ.

- انقر على خلية الرمز البرمجي، ثم اكتب نص cli البرمجي أدناه لإنشاء حزمة GCS، ثم انقر على الزر "تشغيل الخلية" أو اضغط على Shift + Enter.
!gsutil mb -p <your_project_id> -c STANDARD -l US gs://ioxid2025-<your_project_id>
عدِّل قيم <your_project_id> وفقًا لما اخترته أثناء إنشاء مشروع Google Cloud. عدِّل قيم <your_project_id> باستخدام معرّف مشروعك لإنشاء اسم حزمة فريد في GCS. بعد ذلك، انقر على الزر "تشغيل الخلية" أو اضغط على Shift + Enter لتشغيل خلية الرمز.
بعد ذلك، سنبدأ جلسة Spark. في هذا الدرس التطبيقي حول الترميز، سنستخدم مكتبة SparkSession، على الرغم من أنّه يمكننا استخدام DataprocSession للاستفادة من إمكانات Dataproc لتشغيل Spark في ورقة ملاحظات BigQuery Studio.
- انقر على خلية الرمز البرمجي، ثم اكتب نص cli البرمجي أدناه لبدء جلسة Spark. انقر على زر "تشغيل الخلية" أو اضغط على Shift + Enter.
# Import required libraries
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, sum, count, countDistinct, when, expr, date_format
from pyspark.sql.types import DecimalType
# Initialize Spark session with BigQuery connector
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, sum, count, countDistinct, when, expr, date_format
from pyspark.sql.types import DecimalType
# Initialize Spark session with BigQuery connector
spark = SparkSession.builder \
.appName("Google Analytics ETL with Apache Spark") \
.config("spark.jars.packages", "com.google.cloud.spark:spark-bigquery-with-dependencies_2.12:0.32.0") \
.getOrCreate()
spark
الناتج المتوقّع :
SparkSession - in-memory SparkContext Spark UI Version v3.5.4 Master local[*] AppName Google Analytics ETL with Apache Spark
- انقر على خلية الرمز ثم اكتب نصًا برمجيًا لواجهة سطر الأوامر أدناه لضبط مشروع Google Cloud Platform وحزمة GCS المؤقتة.
# Set GCP project and temporary bucket
project_id = "your-gcp-project-id" # Replace with your GCP project ID
bucket = "your-gcs-bucket" # Replace with your GCS bucket for temporary files spark.conf.set("temporaryGcsBucket", bucket)
قاعدة بيانات العيّنات في "إحصاءات Google"
يتم توفير قاعدة بيانات عيّنة "إحصاءات Google" على BigQuery من خلال برنامج مجموعات البيانات العامة في Google Cloud. توفّر مجموعة البيانات 12 شهرًا (من أغسطس 2016 إلى أغسطس 2017) من بيانات "إحصاءات Google 360" التي تم إخفاء مفاتيح فك تشفيرها من متجر بيع سلع Google ، وهو متجر تجارة إلكترونية فعلي يبيع سلعًا تحمل علامة Google التجارية، في BigQuery. وهي طريقة رائعة لتحليل بيانات النشاط الإعلاني والتعرّف على مزايا استخدام BigQuery لتحليل بيانات "إحصاءات 360". مزيد من المعلومات عن البيانات
وتكون البيانات مُطابِقة لما تراه في العادة لأي موقع تجارة إلكترونية وتتضمّن المعلومات التالية:
- بيانات مصادر الزيارات: معلومات حول مصدر زوّار موقع الويب، بما في ذلك بيانات عن الزيارات الواردة من نتائج البحث المجانية، وزيارات نتائج البحث المدفوعة، وزيارات الشبكة الإعلانية
- بيانات المحتوى: معلومات حول سلوك المستخدمين في الموقع الإلكتروني، مثل عناوين URL للصفحات التي يتصفّحها الزوّار، وكيفية تفاعلهم مع المحتوى، وما إلى ذلك
- بيانات المعاملات: معلومات عن المعاملات التي تتم على موقع متجر بيع سلع Google الإلكتروني.
تشغيل الرمز أدناه لعرض عينة من أفضل 5 بيانات في Apache Spark
# EXTRACT: Read data from BigQuery
print("Extracting data from BigQuery...")
ga_df = spark.read.format("bigquery") \
.option("table", "bigquery-public-data.google_analytics_sample.ga_sessions_20170801") \
.load()
# Show schema sample data
print("Sample data:")
ga_df.show(5, truncate=False)
الناتج المتوقّع :
Extracting data from BigQuery...
Sample data:
+---------+-----------+----------+--------------+--------+---------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------+------+--------+---------------+--------------------+
|visitorId|visitNumber|visitId |visitStartTime|date |totals |trafficSource |device |geoNetwork |customDimensions |hits |fullVisitorId |userId|clientId|channelGrouping|socialEngagementType|
+---------+-----------+----------+--------------+--------+---------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------+------+--------+---------------+--------------------+
|NULL |1 |1501591568|1501591568 |20170801|{1, 1, 1, NULL, 1, NULL, NULL, 1, NULL, NULL, NULL, NULL, 1} |{NULL, (not set), (direct), (none), NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, not available in demo dataset, NULL, NULL, NULL, NULL, NULL}, NULL, NULL} |{Chrome, not available in demo dataset, not available in demo dataset, Windows, not available in demo dataset, false, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, NULL, not available in demo dataset, not available in demo dataset, not available in demo dataset, desktop} |{Europe, Southern Europe, Greece, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, tellas.gr, not available in demo dataset, not available in demo dataset, not available in demo dataset} |[] |[{1, 0, 5, 46, NULL, true, true, true, https://www.google.gr/, {/google+redesign/bags/google+zipper+front+sports+bag.axd, shop.googlemerchandisestore.com, Page Unavailable, NULL, NULL, /google+redesign/, /bags/, /google+zipper+front+sports+bag.axd, }, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, shop.googlemerchandisestore.com/google+redesign/bags/google+zipper+front+sports+bag.axd, shop.googlemerchandisestore.com/google+redesign/bags/google+zipper+front+sports+bag.axd, shop.googlemerchandisestore.com/google+redesign/bags/google+zipper+front+sports+bag.axd, 0}, {NULL, true, NULL, NULL}, NULL, [], [], NULL, NULL, {0, 1, NULL}, [], NULL, [], [], [], PAGE, {NULL, NULL, NULL, NULL, (not set), NULL, No, : }, NULL, NULL, {(not set), Bags, (not set), (not set), (not set), (entrance), (entrance), (entrance), (entrance), (entrance), NULL, 1, NULL, NULL, NULL}, web, []}] |3418334011779872055|NULL |NULL |Organic Search |Not Socially Engaged|
|NULL |2 |1501589647|1501589647 |20170801|{1, 1, 1, NULL, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 1}|{/analytics/web/, (not set), analytics.google.com, referral, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, not available in demo dataset, NULL, NULL, NULL, NULL, NULL}, NULL, NULL}|{Chrome, not available in demo dataset, not available in demo dataset, Windows, not available in demo dataset, false, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, NULL, not available in demo dataset, not available in demo dataset, not available in demo dataset, desktop} |{Asia, Southern Asia, India, Maharashtra, (not set), Mumbai, not available in demo dataset, unknown.unknown, not available in demo dataset, not available in demo dataset, not available in demo dataset} |[{4, APAC}] |[{1, 0, 5, 14, NULL, true, true, true, https://analytics.google.com/analytics/web/, {/google+redesign/shop+by+brand/youtube, shop.googlemerchandisestore.com, Page Unavailable, NULL, NULL, /google+redesign/, /shop+by+brand/, /youtube, }, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, shop.googlemerchandisestore.com/google+redesign/shop+by+brand/youtube, shop.googlemerchandisestore.com/google+redesign/shop+by+brand/youtube, shop.googlemerchandisestore.com/google+redesign/shop+by+brand/youtube, 0}, {NULL, true, NULL, NULL}, NULL, [], [], NULL, NULL, {0, 1, NULL}, [], NULL, [], [], [], PAGE, {NULL, NULL, NULL, NULL, (not set), NULL, No, : }, NULL, NULL, {(not set), Brands, (not set), (not set), (not set), (entrance), (entrance), (entrance), (entrance), (entrance), NULL, 1, NULL, NULL, NULL}, web, []}] |2474397855041322408|NULL |NULL |Referral |Not Socially Engaged|
|NULL |1 |1501616621|1501616621 |20170801|{1, 1, 1, NULL, 1, NULL, NULL, 1, NULL, NULL, NULL, NULL, 1} |{/analytics/web/, (not set), analytics.google.com, referral, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, not available in demo dataset, NULL, NULL, NULL, NULL, NULL}, NULL, NULL}|{Chrome, not available in demo dataset, not available in demo dataset, Windows, not available in demo dataset, false, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, NULL, not available in demo dataset, not available in demo dataset, not available in demo dataset, desktop} |{Europe, Northern Europe, United Kingdom, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, as9105.com, not available in demo dataset, not available in demo dataset, not available in demo dataset} |[{4, EMEA}] |[{1, 0, 12, 43, NULL, true, true, true, https://analytics.google.com/analytics/web/?utm_source=demoaccount&utm_medium=demoaccount&utm_campaign=demoaccount, {/google+redesign/shop+by+brand/youtube, shop.googlemerchandisestore.com, Page Unavailable, NULL, NULL, /google+redesign/, /shop+by+brand/, /youtube, }, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, shop.googlemerchandisestore.com/google+redesign/shop+by+brand/youtube, shop.googlemerchandisestore.com/google+redesign/shop+by+brand/youtube, shop.googlemerchandisestore.com/google+redesign/shop+by+brand/youtube, 0}, {NULL, true, NULL, NULL}, NULL, [], [], NULL, NULL, {0, 1, NULL}, [], NULL, [], [], [], PAGE, {NULL, NULL, NULL, NULL, (not set), NULL, No, : }, NULL, NULL, {(not set), Brands, (not set), (not set), (not set), (entrance), (entrance), (entrance), (entrance), (entrance), NULL, 1, NULL, NULL, NULL}, web, []}]|5870462820713110108|NULL |NULL |Referral |Not Socially Engaged|
|NULL |1 |1501601200|1501601200 |20170801|{1, 1, 1, NULL, 1, NULL, NULL, 1, NULL, NULL, NULL, NULL, 1} |{/analytics/web/, (not set), analytics.google.com, referral, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, not available in demo dataset, NULL, NULL, NULL, NULL, NULL}, NULL, NULL}|{Firefox, not available in demo dataset, not available in demo dataset, Windows, not available in demo dataset, false, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, NULL, not available in demo dataset, not available in demo dataset, not available in demo dataset, desktop}|{Americas, Northern America, United States, Texas, Dallas-Ft. Worth TX, Dallas, not available in demo dataset, h5colo.com, not available in demo dataset, not available in demo dataset, not available in demo dataset} |[{4, North America}]|[{1, 0, 8, 26, NULL, true, true, true, https://analytics.google.com/analytics/web/, {/google+redesign/shop+by+brand/youtube, shop.googlemerchandisestore.com, Page Unavailable, NULL, NULL, /google+redesign/, /shop+by+brand/, /youtube, }, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, shop.googlemerchandisestore.com/google+redesign/shop+by+brand/youtube, shop.googlemerchandisestore.com/google+redesign/shop+by+brand/youtube, shop.googlemerchandisestore.com/google+redesign/shop+by+brand/youtube, 0}, {NULL, true, NULL, NULL}, NULL, [], [], NULL, NULL, {0, 1, NULL}, [], NULL, [], [], [], PAGE, {NULL, NULL, NULL, NULL, (not set), NULL, No, : }, NULL, NULL, {(not set), Brands, (not set), (not set), (not set), (entrance), (entrance), (entrance), (entrance), (entrance), NULL, 1, NULL, NULL, NULL}, web, []}] |9397809171349480379|NULL |NULL |Referral |Not Socially Engaged|
|NULL |1 |1501615525|1501615525 |20170801|{1, 1, 1, NULL, 1, NULL, NULL, 1, NULL, NULL, NULL, NULL, 1} |{/analytics/web/, (not set), adwords.google.com, referral, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, not available in demo dataset, NULL, NULL, NULL, NULL, NULL}, NULL, NULL} |{Chrome, not available in demo dataset, not available in demo dataset, Windows, not available in demo dataset, false, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, NULL, not available in demo dataset, not available in demo dataset, not available in demo dataset, desktop} |{Americas, Northern America, United States, not available in demo dataset, not available in demo dataset, not available in demo dataset, not available in demo dataset, (not set), not available in demo dataset, not available in demo dataset, not available in demo dataset}|[{4, North America}]|[{1, 0, 12, 25, NULL, true, true, true, https://adwords.google.com/analytics/web/?__o=cues&authuser=0, {/google+redesign/shop+by+brand/youtube, shop.googlemerchandisestore.com, Page Unavailable, NULL, NULL, /google+redesign/, /shop+by+brand/, /youtube, }, NULL, NULL, NULL, {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, shop.googlemerchandisestore.com/google+redesign/shop+by+brand/youtube, shop.googlemerchandisestore.com/google+redesign/shop+by+brand/youtube, shop.googlemerchandisestore.com/google+redesign/shop+by+brand/youtube, 0}, {NULL, true, NULL, NULL}, NULL, [], [], NULL, NULL, {0, 1, NULL}, [], NULL, [], [], [], PAGE, {NULL, NULL, NULL, NULL, (not set), NULL, No, : }, NULL, NULL, {(not set), Brands, (not set), (not set), (not set), (entrance), (entrance), (entrance), (entrance), (entrance), NULL, 1, NULL, NULL, NULL}, web, []}] |6089902943184578335|NULL |NULL |Referral |Not Socially Engaged|
+---------+-----------+----------+--------------+--------+---------------------------------------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+--------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------+------+--------+---------------+--------------------+
only showing top 5 rows
5- تجميع البيانات حسب متصفّح الجهاز (المقاييس الأساسية)
يجمع هذا الرمز بيانات "إحصاءات Google" حسب متصفّح الجهاز، ويحتسب مقاييس مختلفة مثل إجمالي الجلسات والزيارات والنتائج ومشاهدات الصفحة على الويب وعدد مرات الارتداد والوقت المستغرَق في الموقع والزوار الفرديين ومتوسط الوقت لكل زيارة، ثم يعيد تسمية عمود ويرتّب النتائج.
print("Transformation 1: Aggregating by device browser...")
device_agg = ga_df.groupBy("device.browser") \
.agg(
count("*").alias("total_sessions"),
sum("totals.visits").alias("total_visits"),
sum("totals.hits").alias("total_hits"),
sum("totals.pageviews").alias("total_pageviews"),
sum("totals.bounces").alias("total_bounces"),
sum("totals.timeOnSite").alias("total_time_on_site"),
countDistinct("fullVisitorId").alias("unique_visitors"),
(sum("totals.timeOnSite")/sum("totals.visits")).alias("avg_time_per_visit")
) \
.withColumnRenamed("browser", "device_browser") \
.orderBy("total_sessions", ascending=False)
# Show sample transformed data
print("\nDevice Aggregation Sample:")
device_agg.show(5)
الناتج المتوقّع :
Transformation 1: Aggregating by device browser... Device Aggregation Sample: +-----------------+--------------+------------+----------+---------------+-------------+------------------+---------------+------------------+ | device_browser|total_sessions|total_visits|total_hits|total_pageviews|total_bounces|total_time_on_site|unique_visitors|avg_time_per_visit| +-----------------+--------------+------------+----------+---------------+-------------+------------------+---------------+------------------+ | Chrome| 1900| 1900| 10896| 8956| 870| 354691| 1689|186.67947368421054| | Safari| 397| 397| 1260| 1137| 218| 43150| 364|108.69017632241814| | Firefox| 101| 101| 390| 343| 59| 10659| 95|105.53465346534654| |Internet Explorer| 54| 54| 107| 102| 36| 5589| 50| 103.5| | Edge| 23| 23| 63| 55| 12| 2623| 23|114.04347826086956| +-----------------+--------------+------------+----------+---------------+-------------+------------------+---------------+------------------+ only showing top 5 rows
6. تحليل مصدر الزيارات باستخدام حسابات الأرباح
يحلّل هذا الرمز بيانات "إحصاءات Google" حسب مصدر الزيارات ووسيطها، ويحسب مقاييس مثل عدد الجلسات والمعاملات وإجمالي الإيرادات والإيرادات لكل جلسة والزوّار الفريدين، ثم يعيد تسمية الأعمدة ويرتّب النتائج حسب إجمالي الإيرادات.
print("Transformation 2: Analyzing traffic sources...")
traffic_source_agg = ga_df.groupBy("trafficSource.source", "trafficSource.medium") \
.agg(
count("*").alias("session_count"),
sum(when(col("totals.transactions").isNotNull(), 1).otherwise(0)).alias("transactions"),
sum("totals.totalTransactionRevenue").cast(DecimalType(20,2)).alias("total_revenue"),
(sum("totals.totalTransactionRevenue")/count("*")).cast(DecimalType(10,2)).alias("revenue_per_session"),
countDistinct("fullVisitorId").alias("unique_visitors")
) \
.withColumnRenamed("source", "traffic_source") \
.withColumnRenamed("medium", "traffic_medium") \
.orderBy("total_revenue", ascending=False)
print("\nTraffic Source Aggregation Sample:")
traffic_source_agg.show(5)
الناتج المتوقّع :
Transformation 2: Analyzing traffic sources... Traffic Source Aggregation Sample: +--------------------+--------------+-------------+------------+-------------+-------------------+---------------+ | traffic_source|traffic_medium|session_count|transactions|total_revenue|revenue_per_session|unique_visitors| +--------------------+--------------+-------------+------------+-------------+-------------------+---------------+ | (direct)| (none)| 2166| 42|8872040000.00| 4096048.01| 1943| | mail.google.com| referral| 2| 1| 17960000.00| 8980000.00| 2| | google.com.tw| referral| 1| 0| NULL| NULL| 1| |analytics.google.com| referral| 57| 0| NULL| NULL| 53| | quora.com| referral| 6| 0| NULL| NULL| 5| +--------------------+--------------+-------------+------------+-------------+-------------------+---------------+ only showing top 5 rows
7. التحليل الجغرافي
ينفّذ هذا الرمز تحليلًا جغرافيًا لبيانات "إحصاءات Google" حسب البلد والمنطقة، ويحتسب عدد الجلسات وإجمالي عدد مرّات مشاهدة الصفحة وإجمالي الوقت المستغرَق في الموقع ومتوسّط الوقت لكلّ جلسة والزوّار الفريدين، ثمّ يعيد تسمية الأعمدة ويفرزها حسب عدد الجلسات.
print("Transformation 3: Geographic analysis...")
geo_agg = ga_df.groupBy("geoNetwork.country", "geoNetwork.region") \
.agg(
count("*").alias("session_count"),
sum("totals.pageviews").alias("total_pageviews"),
sum("totals.timeOnSite").alias("total_time_on_site"),
(sum("totals.timeOnSite")/count("*")).alias("avg_time_per_session"),
countDistinct("fullVisitorId").alias("unique_visitors")
) \
.withColumnRenamed("country", "country") \
.withColumnRenamed("region", "region") \
.orderBy("session_count", ascending=False)
print("\nGeographic Aggregation Sample:")
geo_agg.show(5)
الناتج المتوقّع :
Transformation 3: Geographic analysis... Geographic Aggregation Sample: +--------------+--------------------+-------------+---------------+------------------+--------------------+---------------+ | country| region|session_count|total_pageviews|total_time_on_site|avg_time_per_session|unique_visitors| +--------------+--------------------+-------------+---------------+------------------+--------------------+---------------+ | United States|not available in ...| 564| 2326| 97829| 173.45567375886526| 494| | United States| California| 420| 3102| 116563| 277.5309523809524| 347| | United States| New York| 109| 845| 39976| 366.7522935779817| 84| |United Kingdom|not available in ...| 82| 161| 7791| 95.01219512195122| 79| | India|not available in ...| 62| 139| 2869| 46.274193548387096| 61| +--------------+--------------------+-------------+---------------+------------------+--------------------+---------------+ only showing top 5 rows
8. التحليل المستند إلى الوقت
تنفّذ هذه التعليمات البرمجية تحليلًا مستندًا إلى الوقت من خلال استخراج الساعة من العمود visitStartTime، ثم تجمّع البيانات حسب الساعة لاحتساب عدد الجلسات والمعاملات وإجمالي الإيرادات وإجمالي مشاهدات الصفحة لكل ساعة، وأخيرًا ترتيب النتائج حسب الساعة.
print("Transformation 4: Time-based analysis...")
hourly_agg = ga_df.withColumn("hour", date_format(col("visitStartTime").cast("timestamp"), "H")) \
.groupBy("hour") \
.agg(
count("*").alias("session_count"),
sum("totals.transactions").alias("transactions"),
sum("totals.totalTransactionRevenue").cast(DecimalType(20,2)).alias("total_revenue"),
sum("totals.pageviews").alias("total_pageviews")
) \
.orderBy("hour")
print("\nHourly Aggregation Sample:")
hourly_agg.show(5)
الناتج المتوقّع :
Transformation 4: Time-based analysis... Hourly Aggregation Sample: +----+-------------+------------+-------------+---------------+ |hour|session_count|transactions|total_revenue|total_pageviews| +----+-------------+------------+-------------+---------------+ | 0| 87| NULL| NULL| 372| | 1| 102| NULL| NULL| 494| | 10| 67| NULL| NULL| 149| | 11| 73| NULL| NULL| 167| | 12| 99| NULL| NULL| 313| +----+-------------+------------+-------------+---------------+ only showing top 5 rows
9. كتابة النتيجة في جدول BigQuery
يصدّر هذا الرمز أربعة إطارات بيانات مجمّعة (device_agg وtraffic_source_agg وgeo_agg وhourly_agg) إلى جداول منفصلة في Google BigQuery، مع استبدال الجداول الحالية إذا كانت متوفّرة، وذلك باستخدام طريقة الكتابة المباشرة.
# Write to BigQuery tables
print("\nLoading data to BigQuery...")
# Set output tables
device_output_table = f"{project_id}.analytics_sample.device_aggregation"
traffic_output_table = f"{project_id}.analytics_sample.traffic_source_aggregation"
geo_output_table = f"{project_id}.analytics_sample.geo_aggregation"
hourly_output_table = f"{project_id}.analytics_sample.hourly_aggregation"
dataset_id = "demo" # Replace with your BigQuery dataset ID
# Set BigQuery output table
device_output_table = f"{project_id}.{dataset_id}.device_aggregation"
traffic_output_table = f"{project_id}.{dataset_id}.traffic_source_aggregation"
geo_output_table = f"{project_id}.{dataset_id}.geo_aggregation"
hourly_output_table = f"{project_id}.{dataset_id}.hourly_aggregation"
# Write each DataFrame to BigQuery
device_agg.write \
.format("bigquery") \
.option("table", device_output_table) \
.option("writeMethod", "direct") \
.mode("overwrite") \
.save()
traffic_source_agg.write \
.format("bigquery") \
.option("table", traffic_output_table) \
.option("writeMethod", "direct") \
.mode("overwrite") \
.save()
geo_agg.write \
.format("bigquery") \
.option("table", geo_output_table) \
.option("writeMethod", "direct") \
.mode("overwrite") \
.save()
hourly_agg.write \
.format("bigquery") \
.option("table", hourly_output_table) \
.option("writeMethod", "direct") \
.mode("overwrite") \
.save()
التحقّق من جدول الإخراج في BigQuery للتأكّد من حفظ البيانات بنجاح بعد إجراء بعض عمليات التحويل

جدول تجميع الأجهزة

جدول التجميع الجغرافي

جدول التجميع كل ساعة

traffic_source_aggregation

10. تنظيم رمز دفتر ملاحظات BigQuery Studio (اختياري)
يمكنك تنسيق رمز دفتر ملاحظات BigQuery Studio بالطرق التالية:
- جدولة رمز دفتر الملاحظات من Google Cloud Console ( تطبَّق أسعار دفاتر الملاحظات).
- تشغيل رمز دفتر الملاحظات كعبء عمل مجمّع في Dataproc Serverless ( تطبَّق أسعار Dataproc Serverless).
في هذا الدرس التطبيقي حول الترميز، سنستخدم رمز دفتر الملاحظات "جدولة" من وحدة تحكّم Google Cloud.
- في شريط أدوات دفتر الملاحظات، انقر على الجدول الزمني.
- في جزء جدول الملاحظات، في حقل اسم الجدول الزمني، أدخِل اسمًا للجدول الزمني.
- في قسم المصادقة، امنح دفتر الملاحظات الإذن باستخدام بيانات اعتماد المستخدم في حسابك على Google أو حساب خدمة.
- لاستخدام بيانات اعتماد المستخدم في حسابك على Google ( معاينة)، اختَر التنفيذ باستخدام بيانات اعتماد المستخدم.
- لاستخدام حساب خدمة، اختَر التنفيذ باستخدام حساب الخدمة المحدّد، ثم اختَر حساب خدمة.
- في قسم خيارات دفتر الملاحظات، في حقل نموذج وقت التشغيل، اختَر نموذج وقت تشغيل ورقة ملاحظات Colab أو مواصفات وقت التشغيل التلقائية. للحصول على تفاصيل حول إنشاء نموذج وقت تشغيل لورقة ملاحظات Colab، يُرجى الاطّلاع على إنشاء نموذج وقت تشغيل.
- في حقل حزمة Cloud Storage، انقر على تصفّح واختَر حزمة Cloud Storage أو أنشئها. يجب منح حساب الخدمة المحدّد دور مشرف مساحة التخزين (
roles/storage.admin) في إدارة الهوية وإمكانية الوصول (IAM) على الحزمة المحدّدة. لمزيد من المعلومات، اطّلِع على مقالة تفعيل ميزة جدولة دفاتر الملاحظات. - في قسم معدّل تكرار الجدول الزمني، اتّبِع الخطوات التالية:
- في قائمة التكرار، اختَر معدّل تكرار عمليات تشغيل دفتر الملاحظات المُجدوَلة.
- في الحقل في الوقت، أدخِل وقت عمليات تشغيل دفتر الملاحظات المُجدوَلة.
- في قائمة المنطقة الزمنية، اختَر المنطقة الزمنية للجدول الزمني.
- انقر على إنشاء جدول زمني. إذا اخترت التنفيذ باستخدام بيانات اعتماد المستخدم كطريقة مصادقة، عليك تفويض حسابك على Google ( معاينة).

11. تنظيف
لتجنُّب تحمّل رسوم في حسابك على Google Cloud مقابل الموارد المستخدَمة في هذا الدرس التطبيقي حول الترميز، اتّبِع الخطوات التالية:
- في Google Cloud Console، انتقِل إلى صفحة إدارة الموارد.
- في قائمة المشاريع، اختَر المشروع الذي تريد حذفه، ثم انقر على حذف.
- في مربّع الحوار، اكتب رقم تعريف المشروع، ثم انقر على إيقاف لحذف المشروع.
12. تهانينا
لقد انتهيت من إجراء عمليات تحويل البيانات وتحليلها من خلال الاستفادة من Apache Spark بدون خادم في أوراق ملاحظات BigQuery Studio. خلال هذه الرحلة، استكشفت مجموعات البيانات العامة في Google Cloud، ونفّذت عملية استخراج البيانات وتحويلها وتحميلها بدون خادم باستخدام Apache Spark في أداة "أوراق ملاحظات BigQuery Studio"، كما نسّقت أداة "أوراق ملاحظات BigQuery Studio". أحسنت!
الخطوات التالية :
- تنظيم دفتر الملاحظات باستخدام حساب الخدمة لأغراض التشغيل الآلي
- إضافة نص برمجي لمراقبة المدة عند تشغيل مهمة استخراج البيانات وتحويلها وتحميلها
- نشر دفاتر ملاحظات
- استخدِم DataprocSparkSession للاستفادة من إمكانات Apache Spark الموزّعة الحقيقية مع Serverless Dataproc في أوراق ملاحظات BigQuery Studio.
- أنشئ إجراءً مخزَّنًا لـ Apache Spark في BigQuery Studio. يمكن تطبيق مبادئ البرمجة الشيئية بهذه الطريقة لهيكلة رمز PySpark البرمجي من أجل تحسين التنظيم وسهولة إعادة الاستخدام وإمكانية الصيانة.
المراجع :