أرشفة الصور وتحليلها وإنشاء التقارير في Google Workspace السحابة الإلكترونية من Google

1. نظرة عامة

يمثّل هذا الدرس التطبيقي حول الترميز سير عمل محتمل للمؤسسة: أرشفة الصور وتحليلها وإنشاء التقارير. تخيل أنّ مؤسستك تمتلك سلسلة من الصور تستهلك مساحة على مورد محدود. وتريد أرشفة تلك البيانات، وتحليل تلك الصور، والأهم من ذلك، إنشاء تقرير يلخص المواقع الجغرافية المؤرشفة بالإضافة إلى نتائج التحليل، ويكون مجمّعًا وجاهزًا للاستهلاك من قِبل الإدارة. توفّر خدمة Google Cloud الأدوات اللازمة لتحقيق ذلك، باستخدام واجهات برمجة التطبيقات من خطّيَي منتجات تابعَين للشركة، Google Workspace (المعروفة سابقًا باسم G Suite أو Google Apps) وGoogle Cloud (المعروفة سابقًا باسم GCP).

في تصورنا هذا، ستكون لدى المستخدم التجاري صور على Google Drive. من المنطقي دعم تلك الحالات في "درجة برودة"، مساحة تخزين أقل تكلفة، مثل فئات التخزين المتاحة في Google Cloud Storage تسمح منصة Google Cloud Vision للمطوّرين بدمج ميزات كشف الرؤية بسهولة في التطبيقات، بما في ذلك اكتشاف الأشياء والمعالم، والتعرّف البصري على الأحرف (OCR)، وما إلى ذلك. وأخيرًا، جدول بيانات جداول بيانات Google هو أداة تصوير مفيدة لتلخيص كل هذه الأمور لرئيسك في العمل.

بعد الانتهاء من هذا الدرس التطبيقي حول الترميز لإنشاء حلّ يستفيد من جميع ميزات Google Cloud، نأمل أن تكون مصدر إلهامك لإنشاء تطبيق أكثر تأثيرًا لمؤسستك أو عملائك.

ما ستتعرَّف عليه

  • كيفية استخدام Cloud Shell
  • طريقة مصادقة طلبات البيانات من واجهة برمجة التطبيقات
  • كيفية تثبيت مكتبة عملاء Google APIs للغة Python
  • كيفية تفعيل Google APIs
  • كيفية تنزيل الملفات من Google Drive
  • كيفية تحميل الكائنات أو الكائنات الثنائية الكبيرة (blob) إلى Cloud Storage
  • كيفية تحليل البيانات باستخدام Cloud Vision
  • كيفية كتابة صفوف في "جداول بيانات Google"

المتطلبات

  • حساب على Google (قد تتطلّب حسابات Google Workspace موافقة المشرف)
  • مشروع على Google Cloud مع حساب فوترة نشط على Google Cloud
  • الإلمام بالأوامر الطرفية/أوامر واجهة المستخدم في نظام التشغيل
  • المهارات الأساسية في Python (2 أو 3)، ولكن يمكنك استخدام أي لغة معتمَدة

تجدر الإشارة إلى أنّ امتلاك خبرة في منتجات Google Cloud الأربعة المذكورة أعلاه قد يكون مفيدًا، ولكنّه ليس مطلوبًا. إذا سمح لك الوقت بالتعرّف عليها بشكل منفصل أولاً، يمكنك إجراء دروس تطبيقية حول الترميز لكل منها قبل بدء التمرين هنا:

استطلاع

كيف ستستخدم هذا البرنامج التعليمي؟

القراءة فقط اقرأها وأكمِل التمارين

كيف تقيّم تجربتك مع Python؟

حديث متوسط بارع

ما هو تقييمك لتجربتك في استخدام خدمات Google Cloud؟

حديث متوسط بارع

ما هو تقييمك لتجربتك في استخدام خدمات المطوّرين على Google Workspace؟

حديث متوسط بارع

هل تريد مشاهدة المزيد من المحتوى "الموجهة نحو الأعمال" الدروس التطبيقية حول الترميز مقارنةً بتلك التي هي مقدمات حول ميزات المنتج؟

نعم لا المزيد من الاثنين

2. الإعداد والمتطلبات

إعداد بيئة ذاتية

  1. سجِّل الدخول إلى Google Cloud Console وأنشئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • اسم المشروع هو الاسم المعروض للمشاركين في هذا المشروع. وهي سلسلة أحرف لا تستخدمها Google APIs. ويمكنك تعديله في أي وقت.
  • يجب أن يكون رقم تعريف المشروع فريدًا في جميع مشاريع Google Cloud وغير قابل للتغيير (لا يمكن تغييره بعد ضبطه). تنشئ Cloud Console سلسلة فريدة تلقائيًا. فعادةً لا تهتم بما هو. في معظم الدروس التطبيقية حول الترميز، يجب الإشارة إلى رقم تعريف المشروع (يتم تحديده عادةً على أنّه PROJECT_ID). وإذا لم يعجبك المعرّف الذي تم إنشاؤه، يمكنك إنشاء رقم تعريف عشوائي آخر. ويمكنك بدلاً من ذلك تجربة طلبك الخاص ومعرفة ما إذا كان متوفّرًا. ولا يمكن تغييره بعد هذه الخطوة وسيبقى طوال مدة المشروع.
  • لمعلوماتك، هناك قيمة ثالثة، وهي رقم المشروع الذي تستخدمه بعض واجهات برمجة التطبيقات. اطّلِع على مزيد من المعلومات حول هذه القيم الثلاث في المستندات.
  1. بعد ذلك، عليك تفعيل الفوترة في Cloud Console لاستخدام الموارد/واجهات برمجة التطبيقات في Cloud. إنّ تنفيذ هذا الدرس التطبيقي حول الترميز لن يكون مكلفًا أو مكلفًا على الإطلاق. لإيقاف تشغيل الموارد حتى لا تتحمل الفوترة بعد هذا البرنامج التعليمي، يمكنك حذف الموارد التي أنشأتها أو حذف المشروع بالكامل. يكون مستخدمو Google Cloud الجدد مؤهَّلون للانضمام إلى برنامج فترة تجريبية مجانية بقيمة 300 دولار أمريكي.

بدء Cloud Shell

ملخّص

يمكنك تطوير الرموز البرمجية محليًا على الكمبيوتر المحمول، إلا أنّ الهدف الثانوي من هذا الدرس التطبيقي هو تعليمك كيفية استخدام Google Cloud Shell، وهي بيئة سطر أوامر تعمل في السحابة الإلكترونية عبر متصفّح الويب الحديث.

تفعيل Cloud Shell

  1. من Cloud Console، انقر على تفعيل Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

إذا لم يسبق لك بدء تشغيل Cloud Shell، ستظهر لك شاشة وسيطة (الجزء السفلي غير المرئي من الصفحة) تصف ماهيتها. إذا كان الأمر كذلك، فانقر على متابعة (ولن تراه مرة أخرى مطلقًا). إليك ما تبدو عليه هذه الشاشة التي تُستخدم لمرة واحدة:

9c92662c6a846a5c.png

من المفترَض أن تستغرق عملية إدارة الحسابات والاتصال بخدمة Cloud Shell بضع دقائق فقط.

9f0e51b578fecce5.png

يتم تحميل هذا الجهاز الافتراضي مع جميع أدوات التطوير التي تحتاجها. وتوفّر هذه الشبكة دليلاً رئيسيًا دائمًا بسعة 5 غيغابايت ويتم تشغيله في Google Cloud، ما يحسّن بشكل كبير من أداء الشبكة والمصادقة. يمكنك تنفيذ معظم عملك، إن لم يكن كلّه، في هذا الدرس التطبيقي حول الترميز باستخدام متصفّح أو جهاز Chromebook.

بعد الربط بخدمة Cloud Shell، من المفترض أن ترى أنّه قد تمت مصادقتك وأنّ المشروع معيّن سبق أن تم ضبطه على رقم تعريف مشروعك.

  1. شغِّل الأمر التالي في Cloud Shell لتأكيد مصادقتك:
gcloud auth list

مخرجات الأمر

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. شغّل الأمر التالي في Cloud Shell للتأكد من معرفة الأمر gcloud بمشروعك:
gcloud config list project

مخرجات الأمر

[core]
project = <PROJECT_ID>

إذا لم يكن كذلك، يمكنك تعيينه من خلال هذا الأمر:

gcloud config set project <PROJECT_ID>

مخرجات الأمر

Updated property [core/project].

3- تأكيد بيئة Python

يتطلّب هذا الدرس التطبيقي حول الترميز استخدام لغة Python (على الرغم من توفُّر العديد من اللغات في مكتبات عملاء Google APIs، لذلك لا تتردد في إنشاء شيء مكافئ في أداة التطوير المفضَّلة لديك واستخدام لغة Python كرمز زائف). بشكل خاص، يتوافق هذا الدرس التطبيقي حول الترميز مع Python 2 و3، ولكننا ننصح بالانتقال إلى 3.x في أقرب وقت ممكن.

إنّ Cloud Shell هي أداة ملائمة متاحة للمستخدمين مباشرةً من Cloud Console ولا تتطلّب بيئة تطوير محلية، وبالتالي يمكن تنفيذ هذا الدليل التوجيهي بالكامل في السحابة الإلكترونية باستخدام متصفّح ويب. وبشكل أكثر تحديدًا في هذا الدرس التطبيقي حول الترميز، سبق أن تم تثبيت كلا الإصدارَين من Python مسبقًا في Cloud Shell.

تم تثبيت IPython في Cloud Shell أيضًا: وهو برنامج ترجمة تفاعلية بلغة Python على مستوى أعلى ننصح به، خاصةً إذا كنت جزءًا من مجتمع علوم البيانات أو تعلُّم الآلة. إذا كان الأمر كذلك، فإن IPython هي أداة الترجمة التلقائية لنظام Jupyter Notebook بالإضافة إلى Colab، وهي دفاتر جوبيتر نوتبوك التي تستضيفها Google Research.

يفضل IPython استخدام مترجم Python 3 أولاً ولكنه يعود إلى Python 2 إذا لم يكن 3.x متاحًا. يمكن الوصول إلى IPython من Cloud Shell ولكن يمكن أيضًا تثبيتها في بيئة تطوير محلية. قم بالإنهاء باستخدام ^D (Ctrl-d) واقبل عرض الخروج. سيظهر مثال على ناتج البدء ipython على النحو التالي:

$ ipython
Python 3.7.3 (default, Mar  4 2020, 23:11:43)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.13.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

إذا لم يكن خيار IPython هو تفضيلك، فإن استخدام مترجم Python تفاعلي عادي (إما Cloud Shell أو بيئة التطوير المحلية) مقبول تمامًا (الخروج أيضًا باستخدام ^D):

$ python
Python 2.7.13 (default, Sep 26 2018, 18:42:22)
[GCC 6.3.0 20170516] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> 
$ python3
Python 3.7.3 (default, Mar 10 2020, 02:33:39)
[GCC 6.3.0 20170516] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>

يفترض الدرس التطبيقي حول الترميز أنّ لديك أداة التثبيت pip (مدير حزم Python وأداة حلّ التبعيات). تأتي مزودة بالإصدار 2.7.9 أو الإصدارات الأحدث أو 3.4 الإصدارات الأحدث. إذا كان لديك إصدار قديم من Python، فراجع هذا الدليل للحصول على تعليمات التثبيت. استنادًا إلى أذوناتك، قد تحتاج إلى الحصول على إذن وصول sudo أو مستخدم متميّز، ولكن هذا لا يحدث بشكل عام. يمكنك أيضًا استخدام pip2 أو pip3 بشكل صريح لتنفيذ pip في إصدارات معيّنة من Python.

ويفترض الجزء المتبقي من الدرس التطبيقي حول الترميز أنّك تستخدم Python 3، وسيتم توفير تعليمات محدّدة للغة Python 2 إذا كانت تختلف كثيرًا عن 3.x.

[اختياري] إنشاء بيئات افتراضية واستخدامها

هذا القسم اختياري ومطلوب فقط للمستخدمين الذين عليهم استخدام بيئة افتراضية لهذا الدرس التطبيقي (وفقًا للشريط الجانبي التحذيري أعلاه). إذا كان لديك Python 3 فقط على جهاز الكمبيوتر الخاص بك، يمكنك ببساطة إصدار هذا الأمر لإنشاء Virtualenv باسم my_env (يمكنك اختيار اسم آخر حسب الرغبة):

virtualenv my_env

ومع ذلك، إذا كانت لديك كل من Python 2 3 على الكمبيوتر، ننصحك بتثبيت واجهة Python 3 الافتراضية التي يمكنك تنفيذها باستخدام -p flag على النحو التالي:

virtualenv -p python3 my_env

أدخِل البيئة الافتراضية التي تم إنشاؤها حديثًا من خلال النقر على "تفعيل". على النحو التالي:

source my_env/bin/activate

تأكَّد من وجودك في البيئة من خلال ملاحظة طلب واجهة المستخدم مسبوقة الآن باسم البيئة الخاصة بك، أي

(my_env) $ 

أصبح بإمكانك الآن pip install أي حزم مطلوبة وتنفيذ التعليمات البرمجية في هذا النشاط وغير ذلك. ومن المزايا الأخرى أنّه في حال تلف النظام تمامًا أو الوقوع في عطل قد يؤدي إلى تلف تثبيت لغة Python الخاص بك، وما إلى ذلك، سيكون بإمكانك إيقاف هذه البيئة بالكامل بدون التأثير في باقي النظام.

4. تثبيت مكتبة برامج Google APIs للغة Python

يتطلّب هذا الدرس التطبيقي حول الترميز استخدام مكتبة برامج Google APIs للغة Python، لذا يمكنك إمّا أن تكون عملية تثبيت بسيطة أو لا تتطلّب منك اتخاذ أي إجراء على الإطلاق.

ننصحك سابقًا باستخدام Cloud Shell لتيسير تنفيذ ذلك. يمكنك إكمال البرنامج التعليمي بالكامل من متصفح ويب في السحابة. هناك سبب آخر لاستخدام Cloud Shell وهو أنّ العديد من أدوات التطوير الشائعة والمكتبات الضرورية مثبَّتة مسبقًا.

*تثبيت مكتبات البرامج

(اختياري) يمكن تخطّي هذا الإجراء في حال استخدام Cloud Shell أو بيئة محلية سبق لك تثبيت مكتبات العملاء فيها. ما عليك سوى إجراء ذلك في حال تطوير البرامج محليًا ولم تثبِّتها (أو لم تكن متأكدًا من أنّك ثبَّتها). أسهل طريقة هي استخدام pip (أو pip3) لتثبيت التطبيق (بما في ذلك تحديث pip بنفسه إذا لزم الأمر):

pip install -U pip google-api-python-client oauth2client

تأكيد التثبيت

يثبّت هذا الأمر مكتبة البرامج بالإضافة إلى أي حزم تعتمد عليها. سواء كنت تستخدم Cloud Shell أو بيئتك الخاصة، تأكَّد من تثبيت مكتبة البرامج من خلال استيراد الحِزم اللازمة والتأكّد من عدم حدوث أخطاء في الاستيراد (أو نتائج):

python3 -c "import googleapiclient, httplib2, oauth2client"

إذا كنت تستخدم Python 2 بدلاً من ذلك (من Cloud Shell)، ستتلقّى تحذيرًا يفيد بأنّه تم إيقاف دعمها:

*******************************************************************************
Python 2 is deprecated. Upgrade to Python 3 as soon as possible.
See https://cloud.google.com/python/docs/python2-sunset

To suppress this warning, create an empty ~/.cloudshell/no-python-warning file.
The command will automatically proceed in  seconds or on any key.
*******************************************************************************

بمجرد الانتهاء من تنفيذ إجراء الاستيراد "test" بنجاح (بدون أخطاء/إخراج)، فأنت جاهز لبدء التحدث إلى واجهات برمجة تطبيقات Google.

ملخّص

بما أن هذا درس تطبيقي متوسط حول الترميز، فإن الافتراض هو أنك تمتلك خبرة مسبقة في إنشاء باستخدام المشروعات في وحدة التحكم. إذا كنت مبتدئًا في استخدام Google APIs وواجهات Google Workspace API تحديدًا، جرِّب الدرس التطبيقي حول الترميز التمهيدي لواجهات برمجة تطبيقات Google Workspace أولاً. بالإضافة إلى ذلك، إذا كنت تعرف كيفية إنشاء بيانات اعتماد حساب مستخدم (أو إعادة استخدامها) الحالي (وليس حساب الخدمة)، عليك إفلات ملف client_secret.json في دليل العمل وتخطّي الوحدة التالية والانتقال إلى "تفعيل Google APIs".

5- *تفويض طلبات واجهة برمجة التطبيقات (تفويض المستخدم)

يمكن تخطّي هذا القسم إذا سبق لك إنشاء بيانات اعتماد تفويض حساب المستخدم وكنت ملمًّا بهذه العملية. وهي تختلف عن تفويض حساب الخدمة الذي تختلف أسلوبه، لذا يُرجى المتابعة أدناه.

مقدمة عن التفويض (بالإضافة إلى المصادقة بعض)

لإرسال طلبات إلى واجهات برمجة التطبيقات، يجب أن يحصل تطبيقك على التفويض المناسب. المصادقة، وهي كلمة مشابهة تصف بيانات اعتماد تسجيل الدخول، ويمكنك المصادقة على نفسك عند تسجيل الدخول إلى حسابك على Google باستخدام معلومات تسجيل الدخول وكلمة المرور. بعد المصادقة، يمكنك تحديد ما إذا كنت، أو الرمز، معتمدًا مثلاً للوصول إلى البيانات، مثل ملفات الكائن الثنائي الكبير (blob) على Cloud Storage أو ملفات المستخدم الشخصية على Google Drive.

تدعم Google APIs أنواعًا متعدّدة من التفويضات، إلا أنّ النوع الأكثر شيوعًا لمستخدمي G Suite API هو تفويض المستخدم لأنّ نموذج التطبيق في هذا الدرس التطبيقي يصل إلى بيانات المستخدمين النهائيين. وعلى هؤلاء المستخدمين النهائيين منح تطبيقك الإذن بالوصول إلى بياناتهم. يعني هذا أنّ الرمز يجب أن يحصل على بيانات اعتماد OAuth2 لحساب المستخدم.

للحصول على بيانات اعتماد OAuth2 لتفويض المستخدم، يمكنك الرجوع إلى مدير واجهة برمجة التطبيقات واختيار "بيانات الاعتماد" علامة التبويب في شريط التنقل الأيسر:

635af008256d323.png

عند الانتقال إلى هناك، سترى جميع بيانات الاعتماد في ثلاثة أقسام منفصلة:

fd2f4133b406d572.png

الأول هو مفاتيح واجهة برمجة التطبيقات، ومعرِّفات عميل OAuth 2.0، وآخر حسابات خدمة OAuth2، نستخدم المعرّف الموجود في المنتصف.

جارٍ إنشاء بيانات الاعتماد

من صفحة "بيانات الاعتماد"، انقر على الزر + إنشاء بيانات اعتماد في الأعلى، والذي سيظهر لك بعد ذلك مربع حوار حيث يمكنك اختيار "معرِّف عميل OAuth":

b17b663668e38787.png

على الشاشة التالية، لديك إجراءان: ضبط "شاشة الموافقة" في تفويض تطبيقك. واختيار نوع التطبيق:

4e0b967c9d70d262.png

إذا لم تكن قد ضبطت شاشة موافقة، سيظهر لك التحذير في وحدة التحكّم، وسيكون عليك ضبطها الآن. (يمكنك تخطّي هذه الخطوات التالية إذا سبق أن تم إعداد شاشة الموافقة).

انقر على "إعداد شاشة الموافقة" حيث تحدد "خارجي" تطبيق (أو "داخلي" إذا كنت أحد عملاء G Suite):

f17e97b30d994b0c.png

لأغراض هذا التمرين، لا يهم أي من اختيارك لأنك لا تنشر عينة من درسك التطبيقي. سيختار معظم المستخدمين "خارجي". ليتم نقله إلى شاشة أكثر تعقيدًا، ولكنك حقًا لا تحتاج سوى إلى إكمال "اسم التطبيق" الحقل في الجزء العلوي:

b107ab81349bdad2.png

كل ما تحتاج إليه في الوقت الحالي هو اسم تطبيق فقط، لذا اختَر مستخدمًا يعكس الدرس التطبيقي حول الترميز الذي تجريه، ثم انقر على حفظ.

إنشاء معرِّف عميل OAuth (مصادقة حساب المستخدم)

عُد الآن إلى علامة التبويب "بيانات الاعتماد" لإنشاء معرِّف عميل OAuth2. ستظهر لك هنا مجموعة متنوعة من معرّفات عملاء OAuth التي يمكنك إنشاؤها:

5ddd365ac0af1e34.png

نحن نعمل على تطوير أداة سطر الأوامر، وهي أخرى، لذا اخترها ثم انقر على الزر إنشاء. اختر اسم معرِّف عميل يعكس التطبيق الذي تُنشئه أو استخدِم الاسم التلقائي الذي يكون عادةً "عميل آخر N".

جارٍ حفظ بيانات الاعتماد.

  1. سيظهر مربع حوار يتضمن بيانات الاعتماد الجديدة. انقر على حسنًا لإغلاق

8bec84d82cb104d7.png

  1. مرة أخرى في صفحة "بيانات الاعتماد"، مرِّر لأسفل وصولاً إلى "معرّفات عميل OAuth2". البحث عن رمز التنزيل f54b28417901b3aa.png والنقر عليه في أسفل يسار معرِّف العميل الذي تم إنشاؤه حديثًا. 1b4e8d248274a338.png
  2. سيؤدي هذا إلى فتح مربّع حوار لحفظ ملف باسم client_secret-LONG-HASH-STRING.apps.googleusercontent.com.json، على الأرجح في مجلد عمليات التنزيل. لذلك، ننصحك باختصارها إلى اسم أسهل مثل client_secret.json (وهو ما يستخدمه التطبيق التجريبي)، ثم حفظه في الدليل/المجلد الذي ستنشئ فيه نموذج التطبيق في هذا الدرس التطبيقي حول الترميز.

ملخّص

باتت جاهزًا لتمكين Google APIs المستخدمة في هذا الدرس التطبيقي حول الترميز. وبالنسبة إلى اسم التطبيق أيضًا في شاشة طلب الموافقة المتعلّقة ببروتوكول OAuth، اخترنا "العرض التوضيحي لواجهة برمجة التطبيقات Vision API"، لذا نتوقّع ظهور هذا الاسم في بعض لقطات الشاشة القادمة.

6- تفعيل واجهات برمجة تطبيقات Google

يستخدم هذا الدرس التطبيقي أربع (4) واجهات برمجة تطبيقات من Google Cloud، وهما زوج من Google Cloud (Cloud Storage وCloud Vision) وزوج آخر من Google Workspace (Google Drive و"جداول بيانات Google"). في ما يلي تعليمات عامة لتفعيل Google APIs. عندما تعرف كيفية تمكين إحدى واجهات برمجة التطبيقات، تتشابه الواجهات الأخرى.

بغض النظر عن واجهة Google API التي تريد استخدامها في تطبيقك، يجب تفعيلها. يمكن تفعيل واجهات برمجة التطبيقات من سطر الأوامر أو من Cloud Console. عملية تفعيل واجهات برمجة التطبيقات متطابقة، لذلك بعد تفعيل واجهة برمجة تطبيقات واحدة، يمكنك تفعيل واجهات برمجة تطبيقات أخرى بطريقة مماثلة.

الخيار 1: واجهة سطر الأوامر gcloud (Cloud Shell أو البيئة المحلية)

على الرغم من أن تفعيل واجهات برمجة التطبيقات من Cloud Console هو الأكثر شيوعًا، إلا أنّ بعض المطوّرين يفضّلون تنفيذ كل شيء من سطر الأوامر. لإجراء ذلك، عليك البحث عن "اسم الخدمة" في واجهة برمجة التطبيقات. يبدو أنّ عنوان URL هو: SERVICE_NAME.googleapis.com. يمكنك العثور على هذه المنتجات في الرسم البياني للمنتجات المتوافقة، أو يمكنك طلبها آليًا باستخدام Google Discovery API.

من خلال هذه المعلومات، وباستخدام Cloud Shell (أو بيئة التطوير المحلية التي تم تثبيت أداة سطر الأوامر gcloud عليها)، يمكنك تفعيل واجهة برمجة تطبيقات أو خدمة، كما يلي:

gcloud services enable SERVICE_NAME.googleapis.com

المثال 1: تفعيل Cloud Vision API

gcloud services enable vision.googleapis.com

المثال 2: تفعيل منصة الحوسبة بدون خادم Google App Engine

gcloud services enable appengine.googleapis.com

مثال 3: تفعيل واجهات برمجة تطبيقات متعددة من خلال طلب واحد على سبيل المثال، إذا كان هذا الدرس التطبيقي حول الترميز يتضمّن مشاهدين ينشرون تطبيقًا باستخدام Cloud Translation API على App Engine وCloud Functions وCloud Run، سيكون سطر الأوامر على النحو التالي:

gcloud services enable appengine.googleapis.com cloudfunctions.googleapis.com artifactregistry.googleapis.com run.googleapis.com translate.googleapis.com

يؤدي هذا الأمر إلى تفعيل App Engine وCloud Functions وCloud Run وCloud Translation API. بالإضافة إلى ذلك، يفعّل Cloud Artifact Registry لأنّه يجب تسجيل صور الحاوية من خلال نظام Cloud Build ليتم نشرها في Cloud Run.

هناك أيضًا بضعة أوامر لطلب البحث عن واجهات برمجة التطبيقات التي يجب تفعيلها أو واجهات برمجة التطبيقات التي سبق تفعيلها لمشروعك.

المثال 4: طلب البحث عن Google APIs المتاحة للتفعيل لمشروعك

gcloud services list --available --filter="name:googleapis.com"

المثال 5: تفعيل طلب البحث عن Google APIs لمشروعك

gcloud services list

لمزيد من المعلومات حول الأوامر الواردة أعلاه، يُرجى الاطِّلاع على مستندات تفعيل الخدمات وإيقافها وإدراج الخدمات.

الخيار 2: Cloud Console

يمكنك أيضًا تفعيل Google APIs في مدير واجهات برمجة التطبيقات. من Cloud Console، انتقِل إلى مدير واجهات برمجة التطبيقات. في صفحة لوحة البيانات هذه، ستظهر لك بعض معلومات زيارات تطبيقك، والرسوم البيانية التي تعرض طلبات تقديم الطلب، والأخطاء التي حدثت في تطبيقك، وأوقات استجابة التطبيق:

df4a0a5e00d29ffc.png

تتوفر أسفل هذه المخططات قائمة بواجهات Google APIs التي تم تفعيلها لمشروعك:

5fcf10e5a05cfb97.png

لتفعيل واجهات برمجة التطبيقات (أو إيقافها)، انقر على تفعيل واجهات برمجة التطبيقات والخدمات في أعلى الصفحة:

eef4e5e863f4db66.png

بدلاً من ذلك، انتقل إلى شريط التنقل الأيمن وحدد واجهات برمجة التطبيقات الخدماتالمكتبة:

6eda5ba145b30b97.png

وفي كلتا الحالتين، ستنتقل إلى صفحة مكتبة واجهة برمجة التطبيقات:

5d4f1c8e7cf8df28.png

أدخِل اسم واجهة برمجة التطبيقات للبحث عن النتائج المطابقة والاطّلاع عليها:

35bc4b9cf72ce9a4.png

اختَر واجهة برمجة التطبيقات التي تريد تفعيلها وانقر على الزر تفعيل:

9574a69ef8d9e8d2.png

تعتبر عملية تفعيل جميع واجهات برمجة التطبيقات مشابهة لعملية تفعيل جميع واجهات برمجة التطبيقات، بغض النظر عن واجهة Google API التي تريد استخدامها.

التكلفة

يمكن استخدام العديد من واجهات Google APIs بدون رسوم، ولكن هناك تكاليف عند استخدام معظم منتجات Google Cloud وواجهات برمجة التطبيقات. عند تفعيل Cloud APIs، قد يُطلَب منك حساب فوترة نشط. ومع ذلك، تقدّم بعض منتجات Google Cloud الحالة "مجانية دائمًا" tier والتي يجب أن تتجاوزها لتحمل تكاليف الفوترة.

يكون مستخدمو Google Cloud الجدد مؤهلين للاستفادة من الفترة التجريبية المجانية، وهي حاليًا صالحة بقيمة 300 دولار أمريكي خلال أول 90 يومًا. لا تتطلب الدروس التطبيقية حول الترميز عادةً الكثير من الفواتير أو أي رسوم فوترة، لذا نقترح عليك إيقاف "الفترة التجريبية المجانية" إلى أن تصبح مستعدًا لاختبارها، لا سيّما أنّها عرض لمرة واحدة. لا تنتهي صلاحية حصص "المستوى المجاني" ولا تسري بغض النظر عما إذا كنت تستخدم الفترة التجريبية المجانية أم لا.

على المستخدمين الرجوع إلى معلومات الأسعار الخاصة بأي واجهة برمجة تطبيقات قبل تفعيلها (على سبيل المثال، صفحة أسعار Cloud Vision API )، لا سيما إذا كانت تتضمّن مستوى مجانيًا، وإذا كان الأمر كذلك، يُرجى توضيح ما إذا كانت تتضمّن فئة مجانية. وما دمت في حدود الحدود اليومية أو الشهرية المحددة بشكل إجمالي، لن تتحمل أي رسوم. تختلف الأسعار والمستويات المجانية بين واجهات برمجة التطبيقات الخاصة بمجموعات المنتجات من Google. أمثلة:

تتم فوترة منتجات Google المختلفة بشكل مختلف، لذا احرص على الرجوع إلى الوثائق المناسبة لهذه المعلومات.

ملخّص

الآن بعد تفعيل Cloud Vision، يمكنك تفعيل واجهات برمجة التطبيقات الثلاث الأخرى (Google Drive وCloud Storage و"جداول بيانات Google") بالطريقة نفسها. من Cloud Shell، يمكنك استخدام gcloud services enable أو من Cloud Console:

  1. الرجوع إلى مكتبة واجهة برمجة التطبيقات
  2. ابدأ البحث بكتابة بعض أحرف الاسم
  3. حدد واجهة برمجة التطبيقات المطلوبة،
  4. تفعيل

رغوة غسلها و شطفها وتكرارها. بالنسبة إلى Cloud Storage، تتوفّر عدة خيارات: اختَر "Google Cloud Storage JSON API". وستتوقّع أيضًا Cloud Storage API توفّر حساب فوترة نشط.

7. الخطوة 0: إعداد عمليات الاستيراد & رمز التفويض

هذه بداية جزء متوسط من التعليمات البرمجية، لذا يساعد اتباع الممارسات المرنة إلى حد ما في ضمان بنية أساسية مشتركة وثابتة وقابلة للعمل قبل التعامل مع التطبيق الرئيسي. تحقق مرة أخرى من client_secret.json في الدليل الحالي، ويمكنك إما بدء تشغيل ipython وإدخال مقتطف الرمز التالي، أو حفظه في analyze_gsimg.py وتشغيله من واجهة الأوامر (يفضل استخدام الأخير لأننا سنواصل إضافته إلى عينة التعليمات البرمجية):

from __future__ import print_function

from googleapiclient import discovery, http
from httplib2 import Http
from oauth2client import file, client, tools

# process credentials for OAuth2 tokens
SCOPES = 'https://www.googleapis.com/auth/drive.readonly'
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
    creds = tools.run_flow(flow, store)

# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE  = discovery.build('drive',   'v3', http=HTTP)

يتضمن هذا المكوِّن الأساسي مجموعات رموز لعمليات استيراد الوحدات أو الحِزم، ومعالجة بيانات الاعتماد الخاصة بمصادقة المستخدم، وإنشاء نقاط نهاية لخدمة واجهة برمجة التطبيقات. الأجزاء الرئيسية من التعليمة البرمجية التي يجب مراجعتها:

  • يؤدي استيراد الدالة print() إلى جعل نموذج Python 2-3 هذا متوافقًا، وتوفّر عمليات استيراد مكتبة Google جميع الأدوات اللازمة للاتصال بـ Google APIs.
  • يمثّل المتغيّر SCOPES الأذونات التي يطلبها المستخدم، ولا يتوفّر سوى إذن واحد حاليًا: إذن بقراءة البيانات من Google Drive.
  • تتم قراءة باقي رمز معالجة بيانات الاعتماد في رموز OAuth2 المميّزة المخزَّنة مؤقتًا، وقد يتم تعديلها إلى رمز دخول جديد باستخدام الرمز المميّز لإعادة التحميل في حال انتهاء صلاحية رمز الدخول الأصلي.
  • إذا لم يتم إنشاء أي رموز مميزة أو تعذّر استرداد رمز دخول صالح لسبب آخر، على المستخدم المرور عبر تدفق OAuth2 الثلاثي (3LO): إنشاء مربع الحوار باستخدام الأذونات المطلوبة ومطالبة المستخدم بالقبول. بعد إجراء ذلك، يستمر التطبيق، وبخلاف ذلك، يطرح tools.run_flow() استثناءً ويتوقّف التنفيذ.
  • وبعد أن يمنح المستخدم الإذن، يتم إنشاء عميل HTTP للاتصال بالخادم، ويتم توقيع جميع الطلبات باستخدام بيانات اعتماد المستخدم للأمان. بعد ذلك، يتم إنشاء نقطة نهاية خدمة لواجهة برمجة التطبيقات Google Drive API (الإصدار 3) باستخدام عميل HTTP هذا، ثم يتم تخصيصها إلى DRIVE.

تشغيل التطبيق

في المرة الأولى التي تنفّذ فيها النص البرمجي، لن يحصل على إذن الوصول إلى ملفات المستخدم على Drive (ملفاتك). تظهر النتيجة على النحو التالي عند إيقاف التنفيذ مؤقتًا:

$ python3 ./analyze_gsimg.py
/usr/local/lib/python3.6/site-packages/oauth2client/_helpers.py:255: UserWarning: Cannot access storage.json: No such file or directory
  warnings.warn(_MISSING_FILE_MESSAGE.format(filename))

Your browser has been opened to visit:
    https://accounts.google.com/o/oauth2/auth?client_id=LONG-STRING.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2F&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.readonly&access_type=offline&response_type=code

If your browser is on a different machine then exit and re-run this
application with the command-line parameter

  --noauth_local_webserver

إذا كنت تعمل من خلال Cloud Shell، انتقِل إلى قسم "From Cloud Shell" ثم قم بالتمرير للخلف لمراجعة الشاشات ذات الصلة في "من بيئة التطوير المحلية" عندما يكون ذلك مناسبًا.

من بيئة تطوير محلية

ويتم إيقاف النص البرمجي لسطر الأوامر مؤقتًا عند فتح نافذة متصفح. قد تظهر صفحة تحذير تبدو مخيفة على النحو التالي:

149241d33871a141.png

وهذه مشكلة مشروعة، لأنّك تحاول تشغيل تطبيق يصل إلى بيانات المستخدم. بما أن هذا مجرد تطبيق تجريبي، وأنت المطوّر، نأمل أن تثق بنفسك بدرجة كافية للمتابعة. ولفهم هذا الأمر بشكل أفضل، ضع نفسك مكان المستخدم: يُطلب منك السماح لرمز مستخدم آخر بالوصول إلى بياناتك. إذا كنت تنوي نشر تطبيق كهذا، ستنتقل إلى عملية إثبات الملكية حتى لا تظهر هذه الشاشة للمستخدمين.

بعد النقر على زر "الانتقال إلى "غير آمن" تطبيق" ، سيظهر لك مربع حوار أذونات OAuth2 يبدو كما هو موضح أدناه—نحن نعمل دائمًا على تحسين واجهة المستخدم، لذلك لا تقلق إذا لم تمثل التطابق التام:

a122eb7468d0d34e.png

يعرض مربّع حوار مسار OAuth2 الأذونات التي يطلبها المطوِّر (من خلال المتغيّر SCOPES). في هذه الحالة، تتعلق بالقدرة على العرض والتنزيل من Google Drive للمستخدم. في الرمز البرمجي للتطبيق، تظهر نطاقات الأذونات هذه كمعرّفات موارد منتظمة (URI)، ولكن تتم ترجمتها إلى اللغة التي تحدّدها لغة المستخدم. يجب هنا أن يمنح المستخدم إذنًا صريحًا للأذونات المطلوبة، وإلّا يتم طرح استثناء حتى لا يستمر النص البرمجي.

قد يظهر لك أيضًا مربع حوار آخر يطلب منك التأكيد:

bf171080dcd6ec5.png

ملاحظة: تستخدم بعض المتصفّحات هذه عدّة متصفّحات ويب تم تسجيل الدخول إليها في حسابات مختلفة، لذا قد ينتقل طلب التفويض هذا إلى علامة تبويب/نافذة غير صحيحة في المتصفّح، وقد تحتاج إلى قص ولصق رابط هذا الطلب في متصفِّح تم تسجيل الدخول إليه باستخدام الحساب الصحيح.

من Cloud Shell

من Cloud Shell، لا تنبثق أي نافذة متصفح، ما يسبِّب لك مشكلة. إدراك أنّ رسالة بيانات التشخيص المعروضة في أسفل الصفحة كانت موجَّهة لك:

If your browser is on a different machine then exit and re-run this
application with the command-line parameter

  --noauth_local_webserver

سيتعين عليك الضغط على ^C (بالضغط على Ctrl-C أو ضغطة مفتاح أخرى لإيقاف تنفيذ النص البرمجي)، وتشغيلها من واجهة الأوامر باستخدام العلامة الإضافية. عند إجراء العملية بهذه الطريقة، ستحصل على الناتج التالي بدلاً من ذلك:

$ python3 analyze_gsimg.py --noauth_local_webserver
/usr/local/lib/python3.7/site-packages/oauth2client/_helpers.py:255: UserWarning: Cannot access storage.json: No such file or directory
  warnings.warn(_MISSING_FILE_MESSAGE.format(filename))

Go to the following link in your browser:

    https://accounts.google.com/o/oauth2/auth?client_id=LONG-STRING.apps.googleusercontent.com&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive.readonly&access_type=offline&response_type=code

Enter verification code:

(مع تجاهل التحذير لأنّنا نعلم أنّه لم يتم إنشاء storage.json إلى الآن) ومن خلال اتّباع التعليمات الواردة في علامة تبويب أخرى في المتصفّح باستخدام عنوان URL هذا، ستحصل على تجربة مماثلة تقريبًا لما هو موضح أعلاه لبيئات التطوير المحلية (اطّلِع على لقطات الشاشة أعلاه). في النهاية، توجد شاشة أخيرة تحتوي على رمز التحقق لإدخاله في Cloud Shell:

40a567cda0f31cc9.png

انسخ هذا الرمز والصقه في نافذة الوحدة الطرفية.

ملخّص

بخلاف "Authentication successful"، لا تتوقّع أي نتائج إضافية. تذكر أن هذا مجرد إعداد... لم تفعل أي شيء بعد. ما أنجزته هو بداية رحلتك بنجاح إلى شيء يزيد احتمال تنفيذه بشكل صحيح في المرة الأولى. (وأفضل جزء هو أنّه طُلب منك منح الإذن مرّة واحدة فقط، وأنّ جميع عمليات التنفيذ المتتالية تتخطّاها لأنّه تم تخزين الأذونات مؤقتًا). والآن، لنجعل الرمز يؤدي بعض الإجراءات الفعلية مما ينتج عنه الإخراج الفعلي.

تحديد المشاكل وحلّها

إذا ظهرت لك رسالة خطأ بدلاً من عدم ظهور أي نتيجة، قد يرجع ذلك إلى سبب واحد أو أكثر، ربما يكون السبب التالي:

8. الخطوة 1: تنزيل الصورة من Google Drive

في الخطوة السابقة، اقترحنا إنشاء الرمز باستخدام analyze_gsimg.py وتعديله من هناك. ومن الممكن أيضًا قص ولصق كل شيء مباشرة في iPython أو هيكل Python القياسي، إلا أن الأمر سيكون مرهقًا للغاية حيث سنواصل إنشاء التطبيق على مراحل.

لنفترض أنّه قد تم اعتماد تطبيقك وأنّه تم إنشاء نقطة نهاية خدمة واجهة برمجة التطبيقات. في التعليمة البرمجية، يتم تمثيله بالمتغير DRIVE. لنعثر الآن على ملف صورة على Google Drive

اضبطه على متغيّر باسم NAME. أدخِل ذلك بالإضافة إلى دالة drive_get_img() التالية أسفل الرمز الوارد في الخطوة 0 مباشرةً:

FILE = 'YOUR_IMG_ON_DRIVE'  # fill-in with name of your Drive file

def drive_get_img(fname):
    'download file from Drive and return file info & binary if found'

    # search for file on Google Drive
    rsp = DRIVE.files().list(q="name='%s'" % fname,
            fields='files(id,name,mimeType,modifiedTime)'
    ).execute().get('files', [])

    # download binary & return file info if found, else return None
    if rsp:
        target = rsp[0]  # use first matching file
        fileId = target['id']
        fname = target['name']
        mtype = target['mimeType']
        binary = DRIVE.files().get_media(fileId=fileId).execute()
        return fname, mtype, target['modifiedTime'], binary

تحتوي مجموعة Drive files() على طريقة list() تؤدي إلى تنفيذ طلب بحث (المَعلمة q) للملف المحدّد. يتم استخدام المعلمة fields لتحديد القيم المعروضة التي تهتم بها، لذلك لماذا يتم إرجاع كل شيء وإبطاء العملية إذا كنت لا تهتم بالقيم الأخرى؟ إذا كنت مستخدمًا جديدًا لأقنعة الحقول لفلترة قيم إرجاع واجهة برمجة التطبيقات، يمكنك الاطّلاع على مشاركة المدونة هذه الفيديو. في الحالات الأخرى، يمكنك تنفيذ الطلب وجلب السمة files التي تم عرضها، مع ضبط الإعداد التلقائي على مصفوفة قائمة فارغة في حال عدم العثور على نتائج مطابقة.

في حال عدم العثور على نتائج، سيتم تخطّي باقي الدالة وعرض None (ضمنيًا). وفي حال عدم الحصول على أول ردّ مطابق (rsp[0])، يمكنك عرض اسم الملف ونوع MIME والطابع الزمني لآخر تعديل، وأخيرًا حمولة البيانات الثنائية التي تم استردادها من خلال الدالة get_media() (من خلال رقم تعريف الملف)، وكذلك في مجموعة files(). (قد تختلف أسماء الطرق قليلاً عن مكتبات العملاء اللغوية الأخرى).

والجزء الأخير هو "الرئيسي" النص الذي يقود التطبيق بالكامل:

if __name__ == '__main__':
    # download img file & info from Drive
    rsp = drive_get_img(FILE)
    if rsp:
        fname, mtype, ftime, data = rsp
        print('Downloaded %r (%s, %s, size: %d)' % (fname, mtype, ftime, len(data)))
    else:
        print('ERROR: Cannot download %r from Drive' % fname)

على افتراض أنّ هناك صورة باسم section-work-card-img_2x.jpg على Drive وتم ضبطها على FILE، فعند تنفيذ النص البرمجي بنجاح، من المفترض أن تظهر لك نتيجة تؤكد إمكانية قراءة الملف من Drive (ولكن لم يتم حفظها على جهاز الكمبيوتر):

$ python3 analyze_gsimg.py
Downloaded 'section-work-card-img_2x.jpg' (image/jpeg, 2020-02-27T09:27:22.095Z, size: 27781)

تحديد المشاكل وحلّها

إذا لم تحصل على الناتج الناجح كما هو موضح أعلاه، فقد يرجع ذلك إلى سبب واحد أو أكثر، ربما يكون هذا السبب:

ملخّص

في هذا القسم، تعلّمت كيفية (من خلال طلبَين منفصلَين لواجهة برمجة التطبيقات) الاتصال بواجهة برمجة تطبيقات Drive لطلب بحث عن ملف معيّن ثم تنزيله. حالة الاستخدام التجاري: يمكنك أرشفة بيانات Drive وربما تحليلها، كما هو الحال مع أدوات Google Cloud. يجب أن يتطابق رمز تطبيقك في هذه المرحلة مع الرمز الوارد في المستودع علىstep1-drive/analyze_gsimg.py.

يمكنك قراءة المزيد من المعلومات عن تنزيل الملفات على Google Drive هنا أو الاطّلاع على مشاركة المدونة هذه الفيديو. يتطابق هذا الجزء من الدرس التطبيقي حول الترميز تقريبًا مع الدرس التطبيقي حول ترميز واجهات برمجة تطبيقات Google Workspace، فبدلاً من تنزيل ملف، يعرض أول 100 ملف أو مجلد على Google Drive للمستخدم ويستخدِم نطاقًا أكثر تقييدًا.

9. الخطوة 2: أرشفة الملف في Cloud Storage

الخطوة التالية هي إتاحة خدمة Google Cloud Storage. لتنفيذ ذلك، نحتاج إلى استيراد حزمة Python أخرى، وهي io. تأكد من أن القسم العلوي من عمليات الاستيراد يظهر الآن على النحو التالي:

from __future__ import print_function                   
import io

بالإضافة إلى اسم ملف Drive، نحتاج إلى بعض المعلومات حول مكان تخزين هذا الملف على Cloud Storage، وتحديدًا اسم "الحزمة". ستضعه في وأي "مجلد رئيسي" البادئات. مزيد من المعلومات حول هذا الموضوع خلال لحظات:

FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = ''     # YOUR IMG FILE PREFIX                  

لمحة عن مجموعات البيانات: توفّر خدمة Cloud Storage إمكانية تخزين الكائنات الثنائية الكبيرة (blob) غير النموذجية. عند تحميل الملفات هناك، لا يفهم مفهوم أنواع الملفات والإضافات وما إلى ذلك، مثلما يفعل Google Drive. إنها مجرد "كائنات ثنائية صغيرة" إلى Cloud Storage. وعلاوة على ذلك، لا يتوفر مفهوم للمجلدات أو الأدلة الفرعية في Cloud Storage.

نعم، يمكن استخدام شُرط مائلة (/) في أسماء الملفات لتجريد عدة مجلدات فرعية، ولكن في نهاية اليوم، يتم نقل جميع العناصر الثنائية الكبيرة إلى حزمة، وتصبح "/" أحرفًا فقط في أسماء المجلدات. يمكنك الاطّلاع على صفحة اصطلاحات تسمية الكائنات والحِزم لمزيد من المعلومات.

طلبت الخطوة 1 أعلاه نطاق القراءة فقط في Drive. في الوقت الحالي، هذا كل ما تحتاجه. أصبح مطلوبًا الآن إذن التحميل (للقراءة والكتابة) إلى Cloud Storage. غيِّر SCOPES من متغيّر سلسلة واحد إلى مصفوفة (صف بايثون [أو قائمة]) من نطاقات الأذونات لكي يظهر على النحو التالي:

SCOPES = (
    'https://www.googleapis.com/auth/drive.readonly',
    'https://www.googleapis.com/auth/devstorage.full_control',
)                  

يمكنك الآن إنشاء نقطة نهاية للخدمة على Cloud Storage مباشرةً أسفل النقطة الخاصة بخدمة Drive. يُرجى العلم أنّنا أجرينا تغييرات طفيفة على الاستدعاء لإعادة استخدام كائن عميل HTTP نفسه لأنّه لا داعي لإنشاء آخر جديد عندما يمكن أن يكون موردًا مشتركًا.

# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE  = discovery.build('drive',   'v3', http=HTTP)
GCS    = discovery.build('storage', 'v1', http=HTTP)                  

أضِف الآن هذه الدالة (بعد drive_get_img()) التي يتم تحميلها إلى Cloud Storage:

def gcs_blob_upload(fname, bucket, media, mimetype):
    'upload an object to a Google Cloud Storage bucket'

    # build blob metadata and upload via GCS API
    body = {'name': fname, 'uploadType': 'multipart', 'contentType': mimetype}
    return GCS.objects().insert(bucket=bucket, body=body,
            media_body=http.MediaIoBaseUpload(io.BytesIO(media), mimetype),
            fields='bucket,name').execute()

يتطلّب طلب objects.().insert() اسم الحزمة والبيانات الوصفية للملف والكائن الثنائي نفسه. لفلترة القيم المعروضة، يطلب المتغيّر fields اسم الحزمة والكائنات التي يتم عرضها من واجهة برمجة التطبيقات فقط. للتعرف على مزيد من المعلومات حول أقنعة الحقول هذه في طلبات قراءة واجهة برمجة التطبيقات، يمكنك الاطلاع على هذه المشاركة الفيديو.

يمكنك الآن دمج استخدام gcs_blob_upload() في التطبيق الرئيسي:

        # upload file to GCS
        gcsname = '%s/%s'% (PARENT, fname)
        rsp = gcs_blob_upload(gcsname, BUCKET, data, mtype)
        if rsp:
            print('Uploaded %r to GCS bucket %r' % (rsp['name'], rsp['bucket']))
        else:
            print('ERROR: Cannot upload %r to Cloud Storage' % gcsname)

يدمج المتغير gcsname أي "دليل فرعي رئيسي" يتم إلحاقها باسم الملف نفسه، وعندما تسبقها اسم الحزمة، تعطي انطباعًا بأنّك تضع الملف في الأرشيف في "/bucket/parent.../filename". احذف هذا المقطع مباشرةً بعد دالة print() الأولى أعلى عبارة else بحيث يظهر الجزء "main" بأكمله يبدو كما يلي:

if __name__ == '__main__':
    # download img file & info from Drive
    rsp = drive_get_img(FILE)
    if rsp:
        fname, mtype, ftime, data = rsp
        print('Downloaded %r (%s, %s, size: %d)' % (fname, mtype, ftime, len(data)))

        # upload file to GCS
        gcsname = '%s/%s'% (PARENT, fname)
        rsp = gcs_blob_upload(gcsname, BUCKET, data, mtype)
        if rsp:
            print('Uploaded %r to GCS bucket %r' % (rsp['name'], rsp['bucket']))
        else:
            print('ERROR: Cannot upload %r to Cloud Storage' % gcsname)
    else:
        print('ERROR: Cannot download %r from Drive' % fname)

لنفترض أننا نحدد حزمة باسم "vision-demo" مع "analyzed_imgs" كـ "دليل فرعي رئيسي". بعد ضبط هذه المتغيّرات وإعادة تشغيل النص البرمجي، سيتم تنزيل section-work-card-img_2x.jpg من Drive ثم تحميله إلى Cloud Storage، أليس كذلك؟ ليس!

$ python3 analyze_gsimg.py 
Downloaded 'section-work-card-img_2x.jpg' (image/jpeg, 2020-02-27T09:27:22.095Z, size: 27781)
Traceback (most recent call last):
  File "analyze_gsimg.py", line 85, in <module>
    io.BytesIO(data), mimetype=mtype), mtype)
  File "analyze_gsimg.py", line 72, in gcs_blob_upload
    media_body=media, fields='bucket,name').execute()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/googleapiclient/_helpers.py", line 134, in positional_wrapper
    return wrapped(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/googleapiclient/http.py", line 898, in execute
    raise HttpError(resp, content, uri=self.uri)
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://storage.googleapis.com/upload/storage/v1/b/PROJECT_ID/o?fields=bucket%2Cname&alt=json&uploadType=multipart returned "Insufficient Permission">

انظر بعناية، بينما يتم تنزيل Drive بنجاح، تعذّر التحميل إلى Cloud Storage. لماذا؟

السبب في ذلك هو أنّنا عندما فوّضنا هذا التطبيق في الأصل لتنفيذ الخطوة 1، لم نفوّض سوى إذن الوصول للقراءة فقط إلى Google Drive. على الرغم من أننا أضفنا نطاق القراءة والكتابة إلى Cloud Storage، لم نطالب المستخدم مطلقًا بمنح إذن الوصول هذا. ولتنفيذ ذلك، علينا إزالة الملف storage.json الذي لا يتضمّن هذا النطاق ثم إعادة تشغيله.

بعد إعادة التفويض (أكِّد ذلك من خلال الاطّلاع على storage.json ورؤية كلا النطاقَين هناك)، ستكون نتائجك على النحو المتوقّع:

$ python3 analyze_gsimg.py

    . . .

Authentication successful.
Downloaded 'section-work-card-img_2x.jpg' (image/jpeg, 2020-02-27T09:27:22.095Z, size: 27781)
Uploaded 'analyzed_imgs/section-work-card-img_2x.jpg' to GCS bucket 'vision-demo'

ملخّص

ستكون هذه الطريقة مهمة، وهي تظهر لك في عدد قليل نسبيًا من الرموز البرمجية حول كيفية نقل الملفات بين نظامَي التخزين المستنِدَين إلى السحابة الإلكترونية. إن حالة استخدام الأعمال هنا هي نسخ مورد يُحتمل أن يكون مقيدًا إلى "بارد"، مساحة تخزين أرخص كما ذكرنا سابقًا. تقدّم خدمة Cloud Storage فئات مساحة تخزين مختلفة استنادًا إلى ما إذا كان وصولك إلى بياناتك بانتظام أو شهريًا أو ربع سنوي أو سنويًا.

يسألنا مطوّرو البرامج من حين لآخر عن سبب توفُّر كل من Google Drive وCloud Storage. بعد كل شيء، أليس كلاهما كلاهما تخزين الملفات في السحابة؟ لهذا السبب، أنشأنا هذا الفيديو. يجب أن يتطابق الرمز الخاص بك في هذه المرحلة مع البيانات المتوفّرة في المستودع على step2-gcs/analyze_gsimg.py.

10. الخطوة 3: التحليل باستخدام Cloud Vision

نحن نعلم الآن أنّه يمكنك نقل البيانات بين Google Cloud وGoogle Workspace، ولكنّنا لم نُجرِ أي تحليل بعد، لذا حان الوقت لإرسال الصورة إلى Cloud Vision للحصول على تعليق توضيحي للتصنيف، كرصد العناصر. ولتنفيذ ذلك، نحتاج إلى ترميز البيانات باستخدام Base64، وهو ما يعني وحدة Python أخرى باسم base64. تأكد من أن قسم الاستيراد الأول يظهر على النحو التالي:

from __future__ import print_function
import base64
import io

تعرض Vision API تلقائيًا جميع التصنيفات التي تعثر عليها. للحفاظ على اتساق العناصر، لنطلب فقط أهم 5 (قابلة للتعديل من قبل المستخدم بالطبع). سنستخدم متغير ثابت TOP لذلك؛ وإضافته ضمن جميع الثوابت الأخرى:

FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = ''   # YOUR IMG FILE PREFIX 
TOP = 5       # TOP # of VISION LABELS TO SAVE                 

كما هو الحال مع الخطوات السابقة، نحتاج إلى نطاق إذن آخر، ولكن في هذه المرة بالنسبة إلى Vision API. تعديل "SCOPES" باستخدام سلسلة السمة:

SCOPES = (
    'https://www.googleapis.com/auth/drive.readonly',
    'https://www.googleapis.com/auth/devstorage.full_control',
    'https://www.googleapis.com/auth/cloud-vision',
)                  

أنشئ الآن نقطة نهاية للخدمة في Cloud Vision بحيث تتماشى مع النقاط الأخرى مثل هذه:

# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE  = discovery.build('drive',   'v3', http=HTTP)
GCS    = discovery.build('storage', 'v1', http=HTTP)
VISION = discovery.build('vision',  'v1', http=HTTP)

أضف الآن هذه الدالة التي ترسل حمولة الصورة إلى Cloud Vision:

def vision_label_img(img, top):
    'send image to Vision API for label annotation'

    # build image metadata and call Vision API to process
    body = {'requests': [{
                'image':     {'content': img},
                'features': [{'type': 'LABEL_DETECTION', 'maxResults': top}],
    }]}
    rsp = VISION.images().annotate(body=body).execute().get('responses', [{}])[0]

    # return top labels for image as CSV for Sheet (row)
    if 'labelAnnotations' in rsp:
        return ', '.join('(%.2f%%) %s' % (
                label['score']*100., label['description']) \
                for label in rsp['labelAnnotations'])

يتطلب طلب images().annotate() البيانات بالإضافة إلى ميزات واجهة برمجة التطبيقات المطلوبة. يُعد الحد الأقصى للتصنيفات الخمسة الأعلى جزءًا من الحمولة أيضًا (ولكنه اختياري تمامًا). إذا تم الاستدعاء بنجاح، فستعرض الحمولة أهم 5 تصنيفات للكائنات بالإضافة إلى درجة ثقة كائن في الصورة. (في حال عدم ظهور أي ردّ، يمكنك تخصيص قاموس Python فارغًا لضمان عدم ظهور عبارة if التالية). تعمل هذه الدالة ببساطة على تجميع هذه البيانات في سلسلة CSV لاستخدامها في النهاية في تقريرنا.

يجب وضع الأسطر الخمسة التالية التي تستدعي vision_label_img() مباشرةً بعد التحميل بنجاح إلى Cloud Storage:

            # process w/Vision
            rsp = vision_label_img(base64.b64encode(data).decode('utf-8'), TOP)
            if rsp:
                print('Top %d labels from Vision API: %s' % (TOP, rsp))
            else:
                print('ERROR: Vision API cannot analyze %r' % fname)

بعد إجراء هذه الخطوة، من المفترض أن يظهر برنامج التشغيل الرئيسي بالكامل على النحو التالي:

if __name__ == '__main__':
    # download img file & info from Drive
    rsp = drive_get_img(FILE)
    if rsp:
        fname, mtype, ftime, data = rsp
        print('Downloaded %r (%s, %s, size: %d)' % (fname, mtype, ftime, len(data)))

        # upload file to GCS
        gcsname = '%s/%s'% (PARENT, fname)
        rsp = gcs_blob_upload(gcsname, BUCKET, data, mtype)
        if rsp:
            print('Uploaded %r to GCS bucket %r' % (rsp['name'], rsp['bucket']))

            # process w/Vision
            rsp = vision_label_img(base64.b64encode(data).decode('utf-8'), TOP)
            if rsp:
                print('Top %d labels from Vision API: %s' % (TOP, rsp))
            else:
                print('ERROR: Vision API cannot analyze %r' % fname)
        else:
            print('ERROR: Cannot upload %r to Cloud Storage' % gcsname)
    else:
        print('ERROR: Cannot download %r from Drive' % fname)

يجب أن يؤدي حذف storage.json لإعادة تحميل النطاقات وإعادة تشغيل التطبيق المُعدَّل إلى نتائج مشابهة لما يلي، مع ملاحظة إضافة تحليل Cloud Vision:

$ python3 analyze_gsimg.py

    . . .

Authentication successful.
Downloaded 'section-work-card-img_2x.jpg' (image/jpeg, 2020-02-27T09:27:22.095Z, size: 27781)
Uploaded 'analyzed_imgs/section-work-card-img_2x.jpg' to GCS bucket 'vision-demo'
Top 5 labels from Vision API: (89.94%) Sitting, (86.09%) Interior design, (82.08%) Furniture, (81.52%) Table, (80.85%) Room

ملخّص

ليس لدى كل شخص خبرة في مجال تعلُّم الآلة لإنشاء نماذج تعلُّم الآلة وتدريبها لتحليل البيانات. وفّر فريق Google Cloud بعض النماذج المدرَّبة مسبقًا من Google للاستخدام العام ووضعها خلف واجهات برمجة التطبيقات، ما ساعد في إتاحة الذكاء الاصطناعي (AI) تكنولوجيا تعلُّم الآلة للجميع.

إذا كنت مطوّر برامج ويمكنك طلب واجهة برمجة تطبيقات، يمكنك استخدام تعلُّم الآلة. تُعد Cloud Vision واحدة من خدمات واجهة برمجة التطبيقات التي يمكنك استخدامها لتحليل بياناتك. يمكنك الاطّلاع على الميزات الأخرى هنا. يجب أن يتطابق الرمز الآن مع ما هو في Repo على step3-vision/analyze_gsimg.py.

11. الخطوة 4: إنشاء تقرير باستخدام "جداول بيانات Google"

في هذه المرحلة، كنت قادرًا على أرشفة بيانات الشركة وتحليلها، ولكن الناقص هو ملخص لهذا العمل. دعنا ننظم جميع النتائج في تقرير واحد يمكنك تقديمه إلى رئيسك في العمل. ما الأكثر أناقة في الإدارة من جدول البيانات؟

لا حاجة إلى عمليات استيراد إضافية لواجهة Google Sheets API، لأنّ المعلومة الجديدة الوحيدة المطلوبة هي رقم تعريف الملف لجدول بيانات حالي تم تنسيقه وينتظر صف جديد من البيانات، وبالتالي يكون ثابت SHEET. ننصحك بإنشاء جدول بيانات جديد يبدو مشابهًا لما يلي:

4def78583d05300.png

سيظهر عنوان URL لجدول البيانات هذا على النحو التالي: https://docs.google.com/spreadsheets/d/FILE_ID/edit. احصل على FILE_ID ذلك واضبطه على SHEET.

وانتبِهنا أيضًا إلى دالة صغيرة اسمها k_ize() تحوّل وحدات البايت إلى كيلوبايت، وتُعرف بأنّها لغة lambda في Python، لأنّها مؤلفة من سطر واحد بسيط. ويكون كِلا المعاملين المتكاملين مع الثوابت الأخرى على النحو التالي:

k_ize =  lambda b: '%6.2fK' % (b/1000.)  # bytes to kBs
FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = ''     # YOUR IMG FILE PREFIX
SHEET = 'YOUR_SHEET_ID'
TOP = 5       # TOP # of VISION LABELS TO SAVE                 

كما هو الحال مع الخطوات السابقة، نحتاج إلى نطاق إذن آخر، و هذه المرّة الأولى تتطلّب قراءة المحتوى في Sheets API. أصبح لدى "SCOPES" الآن المتطلبات الأربعة التالية:

SCOPES = (
    'https://www.googleapis.com/auth/drive.readonly',
    'https://www.googleapis.com/auth/devstorage.full_control',
    'https://www.googleapis.com/auth/cloud-vision',
    'https://www.googleapis.com/auth/spreadsheets',
)                  

أنشئ الآن نقطة نهاية خدمة في "جداول بيانات Google" بالقرب من التطبيقات الأخرى، بحيث تبدو على النحو التالي:

# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE  = discovery.build('drive',   'v3', http=HTTP)
GCS    = discovery.build('storage', 'v1', http=HTTP)
VISION = discovery.build('vision',  'v1', http=HTTP)
SHEETS = discovery.build('sheets',  'v4', http=HTTP)

وظيفة sheet_append_row() واضحة: يمكنك أخذ صف من البيانات ومعرّف جدول بيانات، ثم إضافة هذا الصف إلى ورقة البيانات تلك:

def sheet_append_row(sheet, row):
    'append row to a Google Sheet, return #cells added'

    # call Sheets API to write row to Sheet (via its ID)
    rsp = SHEETS.spreadsheets().values().append(
            spreadsheetId=sheet, range='Sheet1',
            valueInputOption='USER_ENTERED', body={'values': [row]}
    ).execute()
    if rsp:
        return rsp.get('updates').get('updatedCells')

يتطلب استدعاء spreadsheets().values().append() معرّف ملف ورقة البيانات ونطاق من الخلايا وكيفية إدخال البيانات والبيانات نفسها. رقم تعريف الملف واضح، ويتم تحديد نطاق الخلايا في الترميز A1. نطاق "Sheet1" جدول البيانات بأكمله — وهذه إشارات إلى واجهة برمجة التطبيقات لإلحاق الصف بعد كل البيانات الموجودة في جدول البيانات. هناك خياران بشأن كيفية إضافة البيانات إلى جدول البيانات، وهما "RAW". (أدخل بيانات السلسلة حرفيًا) أو "USER_ENTERED" (اكتب البيانات كما لو أن المستخدم أدخلها على لوحة المفاتيح باستخدام تطبيق "جداول بيانات Google"، مع الحفاظ على أي ميزات لتنسيق الخلية).

إذا تم الاتصال بنجاح، فلن تحتوي القيمة المعروضة على أي شيء مفيد للغاية، لذلك اخترنا تحديث عدد الخلايا بواسطة طلب واجهة برمجة التطبيقات. يوجد أدناه التعليمة البرمجية التي تستدعي هذه الدالة:

                # push results to Sheet, get cells-saved count
                fsize = k_ize(len(data))
                row = [PARENT,
                        '=HYPERLINK("storage.cloud.google.com/%s/%s", "%s")' % (
                        BUCKET, gcsname, fname), mtype, ftime, fsize, rsp
                ]
                rsp = sheet_append_row(SHEET, row)
                if rsp:
                    print('Updated %d cells in Google Sheet' % rsp)
                else:
                    print('ERROR: Cannot write row to Google Sheets')

يحتوي جدول بيانات Google على أعمدة تمثل البيانات مثل أي "دليل فرعي" رئيسي، موقع الملف المؤرشف على Cloud Storage (الحزمة + اسم الملف)، ونوع MIME للملف، وحجم الملف (بالبايت في الأصل، ولكن تم تحويله إلى كيلوبايت عند استخدام k_ize()) وسلسلة تصنيفات Cloud Vision تجدر الإشارة أيضًا إلى أنّ الموقع المؤرشف هو رابط تشعّبي حتى يتمكّن مديرك من النقر عليه لتأكيد الاحتفاظ بنسخة احتياطية منه بأمان.

عند إضافة كتلة الرموز البرمجية أعلاه بعد عرض النتائج من Cloud Vision مباشرةً، اكتمل الآن الجزء الرئيسي الذي يوجّه التطبيق، على الرغم من أنّه معقّد بعض الشيء:

if __name__ == '__main__':
    # download img file & info from Drive
    rsp = drive_get_img(FILE)
    if rsp:
        fname, mtype, ftime, data = rsp
        print('Downloaded %r (%s, %s, size: %d)' % (fname, mtype, ftime, len(data)))

        # upload file to GCS
        gcsname = '%s/%s'% (PARENT, fname)
        rsp = gcs_blob_upload(gcsname, BUCKET, data, mtype)
        if rsp:
            print('Uploaded %r to GCS bucket %r' % (rsp['name'], rsp['bucket']))

            # process w/Vision
            rsp = vision_label_img(base64.b64encode(data).decode('utf-8'))
            if rsp:
                print('Top %d labels from Vision API: %s' % (TOP, rsp))

                # push results to Sheet, get cells-saved count
                fsize = k_ize(len(data))
                row = [PARENT,
                        '=HYPERLINK("storage.cloud.google.com/%s/%s", "%s")' % (
                        BUCKET, gcsname, fname), mtype, ftime, fsize, rsp
                ]
                rsp = sheet_append_row(SHEET, row)
                if rsp:
                    print('Updated %d cells in Google Sheet' % rsp)
                else:
                    print('ERROR: Cannot write row to Google Sheets')
            else:
                print('ERROR: Vision API cannot analyze %r' % fname)
        else:
            print('ERROR: Cannot upload %r to Cloud Storage' % gcsname)
    else:
        print('ERROR: Cannot download %r from Drive' % fname)

من المفترض أن يؤدي حذف storage.json للمرة الأخيرة وإعادة تشغيل التطبيق المُعدَّل إلى الحصول على نتائج مشابهة لما يلي، مع ملاحظة إضافة تحليل Cloud Vision:

$ python3 analyze_gsimg.py

    . . .

Authentication successful.
Downloaded 'section-work-card-img_2x.jpg' (image/jpeg, 2020-02-27T09:27:22.095Z, size: 27781)
Uploaded 'analyzed_imgs/section-work-card-img_2x.jpg' to GCS bucket 'vision-demo'
Top 5 labels from Vision API: (89.94%) Sitting, (86.09%) Interior design, (82.08%) Furniture, (81.52%) Table, (80.85%) Room
Updated 6 cells in Google Sheet

على الرغم من فائدة سطر الإخراج الإضافي، إلا أنه يمكن تصوره بشكل أفضل من خلال إلقاء نظرة خاطفة على جدول بيانات Google المحدث، مع إضافة السطر الأخير (الصف 7 في المثال أدناه) إلى مجموعة البيانات الحالية التي تمت إضافتها سابقًا:

b53a5bc944734652.png

ملخّص

في أول 3 خطوات من هذا البرنامج التعليمي، تمكّنت من الربط بين Google Workspace وGoogle Cloud APIs لنقل البيانات وتحليلها، ما يمثّل 80% من العمل. ومع ذلك، في نهاية المطاف، لا يعني ذلك أي شيء إذا كنت لا تستطيع أن تقدم إلى الإدارة كل ما أنجزته. لعرض النتائج بشكل أفضل، يمكن أن يكون تلخيص جميع النتائج في تقرير تم إنشاؤه مفيدًا جدًا.

لتعزيز فائدة التحليل، بالإضافة إلى كتابة النتائج في جدول بيانات، يتمثل أحد التحسينات الممكنة في فهرسة أهم 5 تصنيفات لكل صورة حتى يمكن إنشاء قاعدة بيانات داخلية تسمح للموظفين المصرح لهم بطلب البحث عن الصور بواسطة فريق البحث، ولكننا نترك ذلك كتدريب للقراء.

في الوقت الحالي، توجد نتائجنا في جدول بيانات ويمكن للإدارة الوصول إليه. يجب أن يتطابق رمز تطبيقك في هذه المرحلة مع الرمز الوارد في المستودع علىstep4-sheets/analyze_gsimg.py. الخطوة الأخيرة هي تنظيف التعليمة البرمجية وتحويلها إلى نص برمجي قابل للاستخدام.

12. *الخطوة الأخيرة: إعادة الهيكلة

(اختياري) من الجيد أن يكون لديك تطبيق يعمل، لكن هل يمكننا تحسينه؟ نعم، خاصةً التطبيق الرئيسي الذي يبدو وكأنه فوضى مختلطة. لنضع ذلك في دالته الخاصة ونقوده إلى السماح بإدخال المستخدم بدلاً من الثوابت الثابتة. سنطبّق ذلك باستخدام وحدة argparse. علاوة على ذلك، لنقم بتشغيل علامة تبويب متصفح الويب لعرض الورقة بمجرد كتابة صف البيانات الخاص بنا إليها. ويمكن تنفيذ ذلك باستخدام الوحدة webbrowser. نسِّق هذه الاستيراد مع غيرها بحيث تبدو أهم الواردات على النحو التالي:

from __future__ import print_function
import argparse
import base64
import io
import webbrowser

ولكي نتمكّن من استخدام هذا الرمز في تطبيقات أخرى، نحتاج إلى القدرة على إيقاف الناتج، لذا لنضيف علامة DEBUG لإجراء ذلك، ونضيف هذا السطر إلى نهاية قسم الثوابت بالقرب من أعلى الصفحة:

DEBUG = False

الآن، حول النص الرئيسي. أثناء قيامنا بإنشاء هذه العينة، كان يجب أن تكون قد بدأت في الشعور "بعدم الارتياح" حيث تضيف التعليمات البرمجية مستوى آخر من التداخل مع كل خدمة مضافة. في هذه الحالة، أنت لست وحدك، لأنّ ذلك يزيد من مدى تعقيد الرمز كما هو موضّح في مشاركة مدوّنة اختبار Google هذه.

باتباع أفضل الممارسات هذه، دعنا نعيد تنظيم الجزء الرئيسي من التطبيق في دالة وreturn عند كل "نقطة استراحة" بدلاً من الدمج (عرض None في حال تعذّر تنفيذ أي خطوة وTrue في حال نجاح كل الخطوات):

def main(fname, bucket, sheet_id, folder, top, debug):
    '"main()" drives process from image download through report generation'

    # download img file & info from Drive
    rsp = drive_get_img(fname)
    if not rsp:
        return
    fname, mtype, ftime, data = rsp
    if debug:
        print('Downloaded %r (%s, %s, size: %d)' % (fname, mtype, ftime, len(data)))

    # upload file to GCS
    gcsname = '%s/%s'% (folder, fname)
    rsp = gcs_blob_upload(gcsname, bucket, data, mtype)
    if not rsp:
        return
    if debug:
        print('Uploaded %r to GCS bucket %r' % (rsp['name'], rsp['bucket']))

    # process w/Vision
    rsp = vision_label_img(base64.b64encode(data).decode('utf-8'))
    if not rsp:
        return
    if debug:
        print('Top %d labels from Vision API: %s' % (top, rsp))

    # push results to Sheet, get cells-saved count
    fsize = k_ize(len(data))
    row = [folder,
            '=HYPERLINK("storage.cloud.google.com/%s/%s", "%s")' % (
            bucket, gcsname, fname), mtype, ftime, fsize, rsp
    ]
    rsp = sheet_append_row(sheet_id, row)
    if not rsp:
        return
    if debug:
        print('Added %d cells to Google Sheet' % rsp)
    return True

إنّها طريقة أكثر إتقانًا ووضوحًا لترك سلسلة if-else متكررة مع الحدّ من تعقيد الرمز كما هو موضّح أعلاه. الجزء الأخير من اللغز هو إنشاء رسم "حقيقي" برنامج التشغيل الرئيسي، مما يسمح للمستخدم بتخصيص المستخدم وتقليل الإخراج (ما لم يكن مطلوبًا):

if __name__ == '__main__':
    # args: [-hv] [-i imgfile] [-b bucket] [-f folder] [-s Sheet ID] [-t top labels]
    parser = argparse.ArgumentParser()
    parser.add_argument("-i", "--imgfile", action="store_true",
            default=FILE, help="image file filename")
    parser.add_argument("-b", "--bucket_id", action="store_true",
            default=BUCKET, help="Google Cloud Storage bucket name")
    parser.add_argument("-f", "--folder", action="store_true",
            default=PARENT, help="Google Cloud Storage image folder")
    parser.add_argument("-s", "--sheet_id", action="store_true",
            default=SHEET, help="Google Sheet Drive file ID (44-char str)")
    parser.add_argument("-t", "--viz_top", action="store_true",
            default=TOP, help="return top N (default %d) Vision API labels" % TOP)
    parser.add_argument("-v", "--verbose", action="store_true",
            default=DEBUG, help="verbose display output")
    args = parser.parse_args()

    print('Processing file %r... please wait' % args.imgfile)
    rsp = main(args.imgfile, args.bucket_id,
            args.sheet_id, args.folder, args.viz_top, args.verbose)
    if rsp:
        sheet_url = 'https://docs.google.com/spreadsheets/d/%s/edit' % args.sheet_id
        print('DONE: opening web browser to it, or see %s' % sheet_url)
        webbrowser.open(sheet_url, new=1, autoraise=True)
    else:
        print('ERROR: could not process %r' % args.imgfile)

في حال نجاح جميع الخطوات، يشغِّل النص البرمجي متصفّح ويب لجدول البيانات المحدَّد حيث تمت إضافة صف البيانات الجديد.

ملخّص

لا حاجة إلى حذف "storage.json" بسبب عدم حدوث أي تغييرات في النطاق. بعد إعادة تشغيل التطبيق المُعدَّل، تظهر نافذة متصفّح جديدة مفتوحة على ورقة البيانات المُعدَّلة، مع سطور إخراج أقل، مع إصدار خيار "-h"، يُظهر للمستخدمين خياراتهم، بما في ذلك -v لاستعادة أسطر الناتج التي تم إلغاؤها في السابق:

$ python3 analyze_gsimg.py
Processing file 'section-work-card-img_2x.jpg'... please wait
DONE: opening web browser to it, or see https://docs.google.com/spreadsheets/d/SHEET_ID/edit

$ python3 analyze_gsimg.py -h
usage: analyze_gsimg.py [-h] [-i] [-t] [-f] [-b] [-s] [-v]

optional arguments:
  -h, --help       show this help message and exit
  -i, --imgfile    image file filename
  -t, --viz_top    return top N (default 5) Vision API labels
  -f, --folder     Google Cloud Storage image folder
  -b, --bucket_id  Google Cloud Storage bucket name
  -s, --sheet_id   Google Sheet Drive file ID (44-char str)
  -v, --verbose    verbose display output

تتيح الخيارات الأخرى للمستخدمين اختيار أسماء مختلفة لملفات Drive، و"الدليل الفرعي" في Cloud Storage. وأسماء الحزم، أعلى الحرف "N" نتائج من معرّفات ملفات Cloud Vision وجدول البيانات (جداول بيانات Google). بعد إجراء هذه التعديلات الأخيرة، من المفترض أن تتطابق النسخة النهائية من الرمز مع البيانات المتوفّرة في المستودع على final/analyze_gsimg.py وهنا، بشكل كامل:

'''
analyze_gsimg.py - analyze Google Workspace image processing workflow

Download image from Google Drive, archive to Google Cloud Storage, send
to Google Cloud Vision for processing, add results row to Google Sheet.
'''

from __future__ import print_function
import argparse
import base64
import io
import webbrowser

from googleapiclient import discovery, http
from httplib2 import Http
from oauth2client import file, client, tools

k_ize = lambda b: '%6.2fK' % (b/1000.) # bytes to kBs
FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = ''     # YOUR IMG FILE PREFIX
SHEET = 'YOUR_SHEET_ID'
TOP = 5       # TOP # of VISION LABELS TO SAVE
DEBUG = False

# process credentials for OAuth2 tokens
SCOPES = (
    'https://www.googleapis.com/auth/drive.readonly',
    'https://www.googleapis.com/auth/devstorage.full_control',
    'https://www.googleapis.com/auth/cloud-vision',
    'https://www.googleapis.com/auth/spreadsheets',
)
store = file.Storage('storage.json')
creds = store.get()
if not creds or creds.invalid:
    flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
    creds = tools.run_flow(flow, store)

# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE  = discovery.build('drive',   'v3', http=HTTP)
GCS    = discovery.build('storage', 'v1', http=HTTP)
VISION = discovery.build('vision',  'v1', http=HTTP)
SHEETS = discovery.build('sheets',  'v4', http=HTTP)


def drive_get_img(fname):
    'download file from Drive and return file info & binary if found'

    # search for file on Google Drive
    rsp = DRIVE.files().list(q="name='%s'" % fname,
            fields='files(id,name,mimeType,modifiedTime)'
    ).execute().get('files', [])

    # download binary & return file info if found, else return None
    if rsp:
        target = rsp[0]  # use first matching file
        fileId = target['id']
        fname = target['name']
        mtype = target['mimeType']
        binary = DRIVE.files().get_media(fileId=fileId).execute()
        return fname, mtype, target['modifiedTime'], binary


def gcs_blob_upload(fname, bucket, media, mimetype):
    'upload an object to a Google Cloud Storage bucket'

    # build blob metadata and upload via GCS API
    body = {'name': fname, 'uploadType': 'multipart', 'contentType': mimetype}
    return GCS.objects().insert(bucket=bucket, body=body,
            media_body=http.MediaIoBaseUpload(io.BytesIO(media), mimetype),
            fields='bucket,name').execute()


def vision_label_img(img, top):
    'send image to Vision API for label annotation'

    # build image metadata and call Vision API to process
    body = {'requests': [{
                'image':     {'content': img},
                'features': [{'type': 'LABEL_DETECTION', 'maxResults': top}],
    }]}
    rsp = VISION.images().annotate(body=body).execute().get('responses', [{}])[0]

    # return top labels for image as CSV for Sheet (row)
    if 'labelAnnotations' in rsp:
        return ', '.join('(%.2f%%) %s' % (
                label['score']*100., label['description']) \
                for label in rsp['labelAnnotations'])


def sheet_append_row(sheet, row):
    'append row to a Google Sheet, return #cells added'

    # call Sheets API to write row to Sheet (via its ID)
    rsp = SHEETS.spreadsheets().values().append(
            spreadsheetId=sheet, range='Sheet1',
            valueInputOption='USER_ENTERED', body={'values': [row]}
    ).execute()
    if rsp:
        return rsp.get('updates').get('updatedCells')


def main(fname, bucket, sheet_id, folder, top, debug):
    '"main()" drives process from image download through report generation'

    # download img file & info from Drive
    rsp = drive_get_img(fname)
    if not rsp:
        return
    fname, mtype, ftime, data = rsp
    if debug:
        print('Downloaded %r (%s, %s, size: %d)' % (fname, mtype, ftime, len(data)))

    # upload file to GCS
    gcsname = '%s/%s'% (folder, fname)
    rsp = gcs_blob_upload(gcsname, bucket, data, mtype)
    if not rsp:
        return
    if debug:
        print('Uploaded %r to GCS bucket %r' % (rsp['name'], rsp['bucket']))

    # process w/Vision
    rsp = vision_label_img(base64.b64encode(data).decode('utf-8'), top)
    if not rsp:
        return
    if debug:
        print('Top %d labels from Vision API: %s' % (top, rsp))

    # push results to Sheet, get cells-saved count
    fsize = k_ize(len(data))
    row = [folder,
            '=HYPERLINK("storage.cloud.google.com/%s/%s", "%s")' % (
            bucket, gcsname, fname), mtype, ftime, fsize, rsp
    ]
    rsp = sheet_append_row(sheet_id, row)
    if not rsp:
        return
    if debug:
        print('Added %d cells to Google Sheet' % rsp)
    return True


if __name__ == '__main__':
    # args: [-hv] [-i imgfile] [-b bucket] [-f folder] [-s Sheet ID] [-t top labels]
    parser = argparse.ArgumentParser()
    parser.add_argument("-i", "--imgfile", action="store_true",
            default=FILE, help="image file filename")
    parser.add_argument("-b", "--bucket_id", action="store_true",
            default=BUCKET, help="Google Cloud Storage bucket name")
    parser.add_argument("-f", "--folder", action="store_true",
            default=PARENT, help="Google Cloud Storage image folder")
    parser.add_argument("-s", "--sheet_id", action="store_true",
            default=SHEET, help="Google Sheet Drive file ID (44-char str)")
    parser.add_argument("-t", "--viz_top", action="store_true",
            default=TOP, help="return top N (default %d) Vision API labels" % TOP)
    parser.add_argument("-v", "--verbose", action="store_true",
            default=DEBUG, help="verbose display output")
    args = parser.parse_args()

    print('Processing file %r... please wait' % args.imgfile)
    rsp = main(args.imgfile, args.bucket_id,
            args.sheet_id, args.folder, args.viz_top, args.verbose)
    if rsp:
        sheet_url = 'https://docs.google.com/spreadsheets/d/%s/edit' % args.sheet_id
        print('DONE: opening web browser to it, or see %s' % sheet_url)
        webbrowser.open(sheet_url, new=1, autoraise=True)
    else:
        print('ERROR: could not process %r' % args.imgfile)

سنحاول تحديث المحتوى في هذا البرنامج التعليمي باستمرار، ولكن ستكون هناك حالات سيحصل فيها المورد على أحدث إصدار من الرمز.

13. تهانينا!

كان هناك بالتأكيد الكثير من التعلّم في هذا الدرس التطبيقي حول الترميز، وقد أنجزت ذلك من خلال البقاء في أحد الدروس الطويلة حول الترميز. ونتيجةً لذلك، كان يتم التعامل مع سيناريو مؤسسي محتمل يتضمّن حوالي 130 سطرًا من لغة Python، مع الاستفادة من كل من Google Cloud وGoogle Workspace، ونقل البيانات بينهما لإنشاء حلّ عملي. لا تتردد في استكشاف مستودع البرامج المفتوحة المصدر لجميع إصدارات هذا التطبيق (مزيد من المعلومات أدناه).

تَنظيم

  1. لا يمكن استخدام Google Cloud APIs مجانًا، بينما تُطبَّق رسوم الاشتراك الشهرية في Google Workspace على واجهات برمجة تطبيقات Google Workspace (لن يكون هناك رسوم شهرية على مستخدمي Gmail)، لذلك لا حاجة إلى تنظيف واجهة برمجة التطبيقات أو إيقافها لمستخدمي Google Workspace. بالنسبة إلى Google Cloud، يمكنك الانتقال إلى لوحة بيانات Cloud Console والاطّلاع على "بطاقة" الفوترة للنفقات المقدرة.
  2. بالنسبة إلى Cloud Vision، يُسمح لك بعدد ثابت من طلبات البيانات من واجهة برمجة التطبيقات شهريًا مجانًا. لذا، طالما تلتزم هذه الحدود، لن تحتاج إلى إيقاف تشغيل أي شيء أو يجب عليك تعطيل أو حذف مشروعك. يمكن العثور على مزيد من المعلومات حول الفوترة والحصة المجانية في Vision API على صفحة الأسعار.
  3. يحصل بعض مستخدمي Cloud Storage على مساحة تخزين مجانية شهريًا. لن يتم تحصيل أي رسوم إذا لم تكن الصور التي وضعتها في الأرشيف باستخدام هذا الدرس التطبيقي حول الترميز تؤدي إلى تجاوز هذه الحصة. يمكنك العثور على مزيد من المعلومات حول فوترة GCS والحصة المجانية في صفحة الأسعار. يمكنك عرض الكائنات الثنائية الكبيرة وحذفها بسهولة من متصفّح Cloud Storage.
  4. قد يكون لاستخدام Google Drive حصة من مساحة التخزين، وفي حال تجاوزها (أو إذا اقتربت من ذلك)، يمكنك استخدام الأداة التي أنشأتها في هذا الدرس التطبيقي حول الترميز لأرشفة تلك الصور في Cloud Storage للحصول على مساحة أكبر على Drive. يمكن العثور على مزيد من المعلومات حول مساحة التخزين في Google Drive في صفحة الأسعار المناسبة لمستخدمي Google Workspace Basic أو مستخدمي Gmail/المستهلكين.

على الرغم من أنّ معظم خطط Google Workspace Business وGoogle Workspace Enterprise تتضمّن مساحة تخزين غير محدودة، قد يتسبب ذلك في ازدحام مجلدات Drive و/أو إرباكها، ويشكّل التطبيق الذي أنشأته في هذا الدليل التوجيهي طريقة رائعة لأرشفة الملفات غير الضرورية وإزالة الملفات غير الضرورية من Google Drive.

إصدارات بديلة

بينما final/analyze_gsimg.py هو "الأخير" الإصدار الرسمي الذي تعمل عليه في هذا البرنامج التعليمي، ليست نهاية القصة. إحدى مشاكل الإصدار النهائي من التطبيق هي أنّه يستخدم مكتبات المصادقة القديمة التي تم إيقافها. لقد اخترنا هذا المسار لأنه في وقت كتابة هذا التقرير، لم تكن مكتبات المصادقة الجديدة متوافقة مع العديد من العناصر الرئيسية: إدارة تخزين رمز OAuth المميز وأمان سلسلة المحادثات.

مكتبات المصادقة الحالية (الأحدث)

يُرجى العِلم أنّ مكتبات المصادقة القديمة لن تكون متاحة في مرحلة معيّنة، لذا ننصحك بمراجعة النُسخ التي تستخدم مكتبات المصادقة الأحدث (الحالية) في مجلد alt في Repo حتى إذا لم تكن متوافقة مع سلسلة المحادثات (يمكنك إنشاء حل خاص بك يكون متوافقًا مع هذه المكتبات). ابحث عن الملفات التي تحتوي أسماؤها على *newauth*.

مكتبات برامج المنتجات في Google Cloud

تنصح Google Cloud جميع المطوّرين باستخدام مكتبات عملاء المنتجات عند استخدام Google Cloud APIs. ولا تتوفّر هذه المكتبات في الوقت الحالي في واجهات برمجة التطبيقات غير التابعة لخدمة Google Cloud. يتيح استخدام المكتبات ذات المستوى الأدنى الاستخدام المتسق لواجهة برمجة التطبيقات ويوفر إمكانية قراءة الميزات بشكل أفضل. على غرار الاقتراح أعلاه، تتوفّر إصدارات بديلة تستخدم مكتبات عملاء منتجات Google Cloud في مجلد alt الخاص بالمستودع لتتمكّن من مراجعتها. ابحث عن الملفات التي تحتوي أسماؤها على *-gcp*.

تفويض حساب الخدمة

عند العمل في السحابة الإلكترونية فقط، لا يكون هناك بيانات يمتلكها الأشخاص أو (البشر)، لذلك يتم استخدام حسابات الخدمة وتفويض حساب الخدمة بشكل أساسي مع Google Cloud. ومع ذلك، تعود ملكية مستندات Google Workspace بشكل عام إلى مستخدمين (بشريين)، ولذلك يستخدم هذا الدليل التوجيهي تفويض حساب المستخدم. ولا يعني ذلك أنّه لا يمكن استخدام واجهات برمجة التطبيقات في Google Workspace مع حسابات الخدمة. وما دامت هذه الحسابات تمتلك مستوى الوصول المناسب، يمكن بالتأكيد استخدامها في التطبيقات. على غرار ما سبق، تتوفّر إصدارات بديلة تستخدم تفويض حساب الخدمة في مجلد alt الخاص بالمستودع لتتمكّن من مراجعتها. ابحث عن الملفات التي تحتوي أسماؤها على *-svc*.

قائمة الإصدارات البديلة

يمكنك العثور أدناه على جميع الإصدارات البديلة من final/analyze_gsimg.py، ويتضمّن كلّ منها واحدًا أو أكثر من السمات الواردة أعلاه. في اسم ملف كل إصدار، ابحث عن:

  • "oldauth" للإصدارات التي تستخدم مكتبات المصادقة القديمة (بالإضافة إلى final/analyze_gsimg.py)
  • "newauth" للمستخدمين الذين يستخدمون مكتبات المصادقة الحالية أو الأحدث
  • "gcp" لهؤلاء الذين يستخدمون مكتبات برامج منتجات Google Cloud، مثل google-cloud-storage وما إلى ذلك
  • "svc" للمستخدمين الذين يستخدمون مصادقة حساب الخدمة ("svc acct") بدلاً من حساب المستخدم

إليك جميع الإصدارات:

اسم الملف

الوصف

final/analyze_gsimg.py

العينة الأولية؛ يستخدم مكتبات المصادقة القديمة

alt/analyze_gsimg-newauth.py

هذا الإذن مماثل لـ final/analyze_gsimg.py، ولكنّه يستخدم مكتبات المصادقة الأحدث.

alt/analyze_gsimg-oldauth-gcp.py

هذا الخيار مماثل لـ final/analyze_gsimg.py، ولكنّه يستخدم مكتبات عملاء منتجات Google Cloud.

alt/analyze_gsimg-newauth-gcp.py

هذا الخيار مماثل لـ alt/analyze_gsimg-newauth.py، ولكنّه يستخدم مكتبات عملاء منتجات Google Cloud.

alt/analyze_gsimg-oldauth-svc.py

مثل final/analyze_gsimg.py ولكن يتم استخدام حساب svc بدلاً من حساب المستخدم.

alt/analyze_gsimg-newauth-svc.py

مثل alt/analyze_gsimg-newauth.py، ولكنّه يستخدم مصادقة حساب svc بدلاً من حساب المستخدم.

alt/analyze_gsimg-oldauth-svc-gcp.py

هذا الإذن مماثل لـ alt/analyze_gsimg-oldauth-svc.py ولكنّه يستخدم مكتبات عملاء المنتجات في Google Cloud ويشبه alt/analyze_gsimg-oldauth-gcp.py، ولكنّه يستخدم مصادقة حساب svc بدلاً من حساب المستخدم.

alt/analyze_gsimg-newauth-svc-gcp.py

هذا الإذن مماثل لـ alt/analyze_gsimg-oldauth-svc-gcp.py، ولكنّه يستخدم مكتبات المصادقة الأحدث.

إلى جانب الإصدار الأصلي final/analyze_gsimg.py، تحصل على جميع التركيبات الممكنة من الحلّ النهائي، بغض النظر عن بيئة تطوير Google API، ويمكنك اختيار الحل الذي يناسب احتياجاتك. اطّلِع أيضًا على alt/README.md للحصول على شرح مماثل.

دراسة إضافية

فيما يلي بعض الأفكار حول كيفية أخذ هذا التمرين خطوة أو خطوتين أبعد. يمكن توسيع مشكلة مجموعة المشاكل التي يمكن للحلّ الحالي التعامل معها، ما يسمح لك بإجراء هذه التحسينات:

  1. (صور متعددة في مجلدات) بدلاً من معالجة صورة واحدة، لنفترض أن لديك صور في مجلدات Google Drive.
  2. (صور متعددة في ملفات ZIP) بدلاً من مجلّد الصور، ماذا عن أرشيفات ZIP التي تحتوي على ملفات صور؟ إذا كنت تستخدم Python، ننصحك بالاطّلاع على وحدة zipfile.
  3. (تحليل تصنيفات الرؤية) يجمّع الصور المتشابهة معًا، ربما يبدأ بالبحث عن التصنيفات الأكثر شيوعًا، ثم التصنيف الثاني الأكثر شيوعًا، وهكذا.
  4. (إنشاء الرسوم البيانية) المتابعة رقم 3، إنشاء رسوم بيانية باستخدام Sheets API استنادًا إلى تحليل وتصنيف Vision API
  5. (تصنيف المستندات) بدلاً من تحليل الصور باستخدام Cloud Vision API، لنفترض أنّ لديك ملفات PDF لتصنيفها باستخدام Cloud Natural Language API. باستخدام الحلول التي قدّمتها أعلاه، يمكن أن تكون ملفات PDF هذه في مجلدات Drive أو أرشيفات ZIP على Drive.
  6. (إنشاء عروض تقديمية) يمكنك استخدام واجهة برمجة تطبيقات "العروض التقديمية من Google" لإنشاء عرض تقديمي من محتوى تقرير "جدول بيانات Google". يمكنك الاطّلاع على مشاركة المدونة هذه للحصول على أفكار جديدة. فيديو حول إنشاء الشرائح من بيانات جدول البيانات.
  7. (التصدير كملف PDF) يمكنك تصدير جدول البيانات و/أو مجموعة الشرائح كملف PDF، ولكن هذه ليست ميزة في واجهات برمجة تطبيقات "جداول بيانات Google" أو "العروض التقديمية من Google". ملاحظة: Google Drive API رصيد إضافي: يمكنك دمج ملفات PDF في "جداول بيانات Google" و"العروض التقديمية من Google" في ملف PDF واحد رئيسي باستخدام أدوات مثل Ghostscript (في نظام التشغيل Linux أو Windows) أو Combine PDF Pages.action (نظام التشغيل Mac OS X).

مزيد من المعلومات

Codelabs

بنود عامة

Google Workspace

Google Cloud

الترخيص

هذا العمل مرخّص بموجب رخصة المشاع الإبداعي 2.0 مع نسب العمل إلى مؤلف عام.