1. Tổng quan
Lớp học lập trình này mô phỏng một quy trình làm việc có thể có của doanh nghiệp: lưu trữ, phân tích hình ảnh và tạo báo cáo. Hãy tưởng tượng tổ chức của bạn có một loạt hình ảnh chiếm dung lượng trên một tài nguyên có hạn. Bạn muốn lưu trữ dữ liệu đó, phân tích những hình ảnh đó và quan trọng nhất là tạo một báo cáo tóm tắt các vị trí đã lưu trữ cùng với kết quả phân tích, được đối chiếu và sẵn sàng để ban quản lý sử dụng. Google Cloud cung cấp các công cụ để thực hiện việc này, sử dụng API từ 2 dòng sản phẩm của mình là Google Workspace (trước đây là G Suite hoặc Google Apps) và Google Cloud (trước đây là GCP).
Trong trường hợp này, người dùng doanh nghiệp sẽ có hình ảnh trên Google Drive. Bạn nên sao lưu những dữ liệu đó vào bộ nhớ "lạnh" và rẻ hơn, chẳng hạn như các lớp lưu trữ có trong Google Cloud Storage. Google Cloud Vision giúp nhà phát triển dễ dàng tích hợp các tính năng sử dụng thị giác máy tính trong ứng dụng, bao gồm cả tính năng phát hiện đối tượng và địa danh, nhận dạng ký tự quang học (OCR), v.v. Cuối cùng, bảng tính Google Trang tính là một công cụ trực quan hoá hữu ích để tóm tắt tất cả những thông tin này cho sếp của bạn.
Sau khi hoàn thành lớp học lập trình này để xây dựng một giải pháp tận dụng tất cả các dịch vụ của Google Cloud, chúng tôi hy vọng bạn sẽ có thêm cảm hứng để xây dựng một giải pháp có tác động lớn hơn nữa cho tổ chức hoặc khách hàng của bạn.
Kiến thức bạn sẽ học được
- Cách sử dụng Cloud Shell
- Cách xác thực các yêu cầu API
- Cách cài đặt thư viện ứng dụng API của Google cho Python
- Cách bật API của Google
- Cách tải tệp xuống từ Google Drive
- Cách tải các đối tượng/blob lên Cloud Storage
- Cách phân tích dữ liệu bằng Cloud Vision
- Cách ghi các hàng vào Google Trang tính
Bạn cần có
- Tài khoản Google (Tài khoản Google Workspace có thể yêu cầu quản trị viên phê duyệt)
- Một dự án trên Google Cloud có tài khoản thanh toán Google Cloud đang hoạt động
- Quen thuộc với các lệnh của thiết bị đầu cuối/shell trong hệ điều hành
- Có kỹ năng cơ bản về Python (2 hoặc 3), nhưng bạn có thể sử dụng bất kỳ ngôn ngữ nào được hỗ trợ
Bạn nên có kinh nghiệm sử dụng 4 sản phẩm của Google Cloud nêu trên, nhưng không bắt buộc. Nếu có thời gian, bạn nên làm quen với từng lớp học lập trình trước khi bắt tay vào bài tập này:
- Giới thiệu về Google Drive (Sử dụng API Google Workspace) (Python)
- Sử dụng Cloud Vision với Python (Python)
- Tạo công cụ báo cáo tuỳ chỉnh bằng API Trang tính (JS/Node)
- Tải các đối tượng lên Google Cloud Storage (không cần viết mã)
Khảo sát
Bạn sẽ sử dụng hướng dẫn này như thế nào?
Bạn đánh giá thế nào về trải nghiệm của mình với Python?
Bạn đánh giá thế nào về trải nghiệm khi sử dụng các dịch vụ của Google Cloud?
Bạn đánh giá thế nào về trải nghiệm khi sử dụng các dịch vụ dành cho nhà phát triển của Google Workspace?
Bạn có muốn xem thêm các lớp học lập trình "dựa trên doanh nghiệp" so với các lớp học lập trình giới thiệu tính năng sản phẩm không?
2. Thiết lập và yêu cầu
Thiết lập môi trường theo tốc độ của riêng bạn
- Đăng nhập vào Google Cloud Console rồi tạo một dự án mới hoặc sử dụng lại một dự án hiện có. Nếu chưa có tài khoản Gmail hoặc Google Workspace, bạn phải tạo một tài khoản.



- Tên dự án là tên hiển thị của những người tham gia dự án này. Đây là một chuỗi ký tự mà các API của Google không sử dụng. Bạn có thể cập nhật thông tin này bất cứ lúc nào.
- Mã dự án phải là duy nhất trên tất cả các dự án trên Google Cloud và không thể thay đổi (bạn không thể thay đổi sau khi đã đặt). Cloud Console sẽ tự động tạo một chuỗi duy nhất; thường thì bạn không cần quan tâm đến chuỗi này. Trong hầu hết các lớp học lập trình, bạn sẽ cần tham chiếu đến Mã dự án (thường được xác định là
PROJECT_ID). Nếu không thích mã nhận dạng được tạo, bạn có thể tạo một mã nhận dạng ngẫu nhiên khác. Hoặc bạn có thể thử tên người dùng của riêng mình để xem tên đó có dùng được hay không. Bạn không thể thay đổi thông tin này sau bước này và thông tin này sẽ giữ nguyên trong suốt thời gian diễn ra dự án. - Để bạn biết, có một giá trị thứ ba là Số dự án mà một số API sử dụng. Tìm hiểu thêm về cả 3 giá trị này trong tài liệu.
- Tiếp theo, bạn cần bật tính năng thanh toán trong Cloud Console để sử dụng các tài nguyên/API trên đám mây. Việc thực hiện lớp học lập trình này sẽ không tốn nhiều chi phí, nếu có. Để tắt các tài nguyên nhằm tránh phát sinh phí thanh toán ngoài hướng dẫn này, bạn có thể xoá các tài nguyên đã tạo hoặc xoá toàn bộ dự án. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí trị giá 300 USD.
Khởi động Cloud Shell
Tóm tắt
Mặc dù có thể phát triển mã cục bộ trên máy tính xách tay, nhưng mục tiêu thứ hai của lớp học lập trình này là hướng dẫn bạn cách sử dụng Google Cloud Shell, một môi trường dòng lệnh chạy trên đám mây thông qua trình duyệt web hiện đại.
Kích hoạt Cloud Shell
- Trong Cloud Console, hãy nhấp vào Kích hoạt Cloud Shell
.

Nếu chưa từng khởi động Cloud Shell, bạn sẽ thấy một màn hình trung gian (bên dưới phần hiển thị đầu tiên) mô tả về Cloud Shell. Nếu vậy, hãy nhấp vào Tiếp tục (và bạn sẽ không bao giờ thấy màn hình này nữa). Sau đây là giao diện của màn hình xuất hiện một lần:

Quá trình cung cấp và kết nối với Cloud Shell chỉ mất vài giây.

Máy ảo này được trang bị tất cả các công cụ phát triển mà bạn cần. Nền tảng này cung cấp một thư mục chính có dung lượng 5 GB và chạy trong Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và hoạt động xác thực. Bạn có thể thực hiện hầu hết, nếu không muốn nói là tất cả, công việc trong lớp học lập trình này chỉ bằng một trình duyệt hoặc Chromebook.
Sau khi kết nối với Cloud Shell, bạn sẽ thấy rằng mình đã được xác thực và dự án đã được đặt thành mã dự án của bạn.
- Chạy lệnh sau trong Cloud Shell để xác nhận rằng bạn đã được xác thực:
gcloud auth list
Đầu ra của lệnh
Credentialed Accounts
ACTIVE ACCOUNT
* <my_account>@<my_domain.com>
To set the active account, run:
$ gcloud config set account `ACCOUNT`
- Chạy lệnh sau trong Cloud Shell để xác nhận rằng lệnh gcloud biết về dự án của bạn:
gcloud config list project
Đầu ra của lệnh
[core] project = <PROJECT_ID>
Nếu không, bạn có thể đặt nó bằng lệnh sau:
gcloud config set project <PROJECT_ID>
Đầu ra của lệnh
Updated property [core/project].
3. Xác nhận môi trường Python
Lớp học lập trình này yêu cầu bạn sử dụng ngôn ngữ Python (mặc dù thư viện ứng dụng API của Google hỗ trợ nhiều ngôn ngữ, nên bạn có thể thoải mái tạo một ứng dụng tương đương trong công cụ phát triển mà bạn yêu thích và chỉ cần sử dụng Python làm mã giả). Cụ thể, lớp học lập trình này hỗ trợ Python 2 và 3, nhưng bạn nên chuyển sang phiên bản 3.x càng sớm càng tốt.
Cloud Shell là một công cụ thuận tiện mà người dùng có thể sử dụng ngay trong Cloud Console và không yêu cầu môi trường phát triển cục bộ. Vì vậy, bạn có thể hoàn thành hướng dẫn này hoàn toàn trên đám mây bằng trình duyệt web. Cụ thể hơn, đối với lớp học lập trình này, Cloud Shell đã cài đặt sẵn cả hai phiên bản Python.
Cloud Shell cũng đã cài đặt IPython: đây là một trình thông dịch Python tương tác cấp cao hơn mà chúng tôi đề xuất, đặc biệt nếu bạn là thành viên của cộng đồng khoa học dữ liệu hoặc học máy. Nếu có, IPython là trình thông dịch mặc định cho Sổ tay Jupyter cũng như Colab, Sổ tay Jupyter do Google Research lưu trữ.
IPython ưu tiên trình thông dịch Python 3 trước nhưng sẽ quay lại Python 2 nếu không có phiên bản 3.x. Bạn có thể truy cập vào IPython từ Cloud Shell, nhưng cũng có thể cài đặt IPython trong môi trường phát triển cục bộ. Thoát bằng tổ hợp phím ^D (Ctrl-d) và chấp nhận ưu đãi để thoát. Ví dụ về kết quả đầu ra khi bắt đầu ipython sẽ có dạng như sau:
$ 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]:
Nếu không thích IPython, bạn hoàn toàn có thể sử dụng trình thông dịch tương tác Python tiêu chuẩn (Cloud Shell hoặc môi trường phát triển cục bộ của bạn) (cũng có thể thoát bằng ^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. >>>
Lớp học lập trình này cũng giả định rằng bạn có công cụ cài đặt pip (trình quản lý gói Python và trình phân giải phần phụ thuộc). Nó đi kèm với các phiên bản 2.7.9 trở lên hoặc 3.4 trở lên. Nếu bạn có phiên bản Python cũ hơn, hãy xem hướng dẫn này để biết hướng dẫn cài đặt. Tuỳ thuộc vào quyền của bạn, bạn có thể cần có quyền sudo hoặc quyền truy cập của siêu người dùng, nhưng thường thì không cần. Bạn cũng có thể sử dụng pip2 hoặc pip3 một cách rõ ràng để thực thi pip cho các phiên bản Python cụ thể.
Phần còn lại của lớp học lập trình giả định rằng bạn đang sử dụng Python 3. Hướng dẫn cụ thể sẽ được cung cấp cho Python 2 nếu hướng dẫn này khác biệt đáng kể so với Python 3.x.
[không bắt buộc] Tạo và sử dụng môi trường ảo
Phần này là không bắt buộc và chỉ thực sự cần thiết cho những người phải sử dụng môi trường ảo cho lớp học lập trình này (theo cảnh báo ở thanh bên phía trên). Nếu chỉ có Python 3 trên máy tính, bạn chỉ cần đưa ra lệnh này để tạo một virtualenv có tên là my_env (bạn có thể chọn tên khác nếu muốn):
virtualenv my_env
Tuy nhiên, nếu có cả Python 2 và 3 trên máy tính, bạn nên cài đặt một virtualenv Python 3 mà bạn có thể thực hiện bằng -p flag như sau:
virtualenv -p python3 my_env
Nhập virtualenv mới tạo bằng cách "kích hoạt" virtualenv đó như sau:
source my_env/bin/activate
Xác nhận rằng bạn đang ở trong môi trường bằng cách quan sát dấu nhắc của trình bao hiện có tên môi trường ở phía trước, tức là
(my_env) $
Giờ đây, bạn có thể pip install mọi gói cần thiết, thực thi mã trong môi trường này, v.v. Một lợi ích khác là nếu làm hỏng hoàn toàn, gặp phải tình huống cài đặt Python bị hỏng, v.v., bạn có thể xoá toàn bộ môi trường này mà không ảnh hưởng đến phần còn lại của hệ thống.
4. Cài đặt thư viện ứng dụng Google API cho Python
Lớp học lập trình này yêu cầu sử dụng Thư viện ứng dụng API của Google cho Python, vì vậy, đây là một quy trình cài đặt đơn giản hoặc bạn có thể không cần làm gì cả.
Trước đây, bạn nên cân nhắc sử dụng Cloud Shell để thuận tiện. Bạn có thể hoàn thành toàn bộ hướng dẫn này trên trình duyệt web trong đám mây. Một lý do khác để sử dụng Cloud Shell là nhiều công cụ phát triển phổ biến và các thư viện cần thiết đã được cài đặt sẵn.
*Cài đặt thư viện ứng dụng
(không bắt buộc) Bạn có thể bỏ qua bước này nếu đang sử dụng Cloud Shell hoặc một môi trường cục bộ mà bạn đã cài đặt thư viện ứng dụng. Bạn chỉ cần thực hiện việc này nếu đang phát triển cục bộ và chưa (hoặc không chắc chắn đã) cài đặt các công cụ này. Cách dễ nhất là sử dụng pip (hoặc pip3) để cài đặt (bao gồm cả việc cập nhật chính pip nếu cần):
pip install -U pip google-api-python-client oauth2client
Xác nhận cài đặt
Lệnh này sẽ cài đặt thư viện ứng dụng cũng như mọi gói mà thư viện đó phụ thuộc vào. Cho dù bạn đang sử dụng Cloud Shell hay môi trường của riêng mình, hãy xác minh rằng thư viện ứng dụng đã được cài đặt bằng cách nhập các gói cần thiết và xác nhận rằng không có lỗi nhập (cũng như không có đầu ra):
python3 -c "import googleapiclient, httplib2, oauth2client"
Nếu sử dụng Python 2 (từ Cloud Shell), bạn sẽ nhận được cảnh báo rằng phiên bản này không còn được hỗ trợ:
******************************************************************************* 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. *******************************************************************************
Sau khi chạy thành công lệnh nhập "test" (không có lỗi/đầu ra), bạn đã sẵn sàng bắt đầu tương tác với các API của Google!
Tóm tắt
Vì đây là một lớp học lập trình trung cấp, nên giả định là bạn đã có kinh nghiệm tạo và sử dụng các dự án trong bảng điều khiển. Nếu bạn mới sử dụng API của Google, đặc biệt là API Google Workspace, hãy thử lớp học lập trình giới thiệu về API Google Workspace trước. Ngoài ra, nếu bạn biết cách tạo (hoặc sử dụng lại) thông tin đăng nhập tài khoản người dùng (không phải tài khoản dịch vụ) hiện có, hãy thả tệp client_secret.json vào thư mục công việc của bạn, bỏ qua mô-đun tiếp theo và chuyển đến phần "Bật Google API".
5. *Uỷ quyền cho các yêu cầu API (uỷ quyền cho người dùng)
Bạn có thể bỏ qua phần này nếu đã tạo thông tin xác thực uỷ quyền tài khoản người dùng và nắm rõ quy trình. Phương thức này khác với phương thức uỷ quyền tài khoản dịch vụ, vì vậy, vui lòng tiếp tục thực hiện các bước bên dưới.
Giới thiệu về việc uỷ quyền (cộng với một số phương thức xác thực)
Để đưa ra yêu cầu cho các API, ứng dụng của bạn cần có quyền uỷ quyền thích hợp. Xác thực là một từ tương tự, mô tả thông tin đăng nhập – bạn xác thực chính mình khi đăng nhập vào Tài khoản Google bằng thông tin đăng nhập và mật khẩu. Sau khi xác thực, bước tiếp theo là liệu bạn (hay đúng hơn là mã của bạn) có được uỷ quyền truy cập vào dữ liệu hay không, chẳng hạn như tệp blob trên Cloud Storage hoặc tệp cá nhân của người dùng trên Google Drive.
Các API của Google hỗ trợ nhiều loại uỷ quyền, nhưng loại phổ biến nhất đối với người dùng G Suite API là uỷ quyền người dùng vì ứng dụng mẫu trong lớp học lập trình này truy cập vào dữ liệu thuộc về người dùng cuối. Những người dùng cuối đó phải cấp quyền cho ứng dụng của bạn truy cập vào dữ liệu của họ. Điều này có nghĩa là mã của bạn phải lấy được thông tin đăng nhập OAuth2 của tài khoản người dùng.
Để lấy thông tin đăng nhập OAuth2 cho việc uỷ quyền người dùng, hãy quay lại trình quản lý API rồi chọn thẻ "Thông tin đăng nhập" trên trình đơn điều hướng bên trái:

Khi truy cập vào trang này, bạn sẽ thấy tất cả thông tin đăng nhập của mình trong 3 phần riêng biệt:

Loại thứ nhất là khoá API, loại thứ hai là mã ứng dụng khách OAuth 2.0 và loại cuối cùng là tài khoản dịch vụ OAuth2 – chúng ta sẽ sử dụng loại ở giữa.
Tạo thông tin đăng nhập
Trên trang Thông tin xác thực, hãy nhấp vào nút + Tạo thông tin xác thực ở trên cùng. Thao tác này sẽ mở ra một hộp thoại để bạn chọn "Mã ứng dụng khách OAuth":

Trên màn hình tiếp theo, bạn có 2 việc cần làm: định cấu hình "màn hình xin phép" uỷ quyền của ứng dụng và chọn loại ứng dụng:

Nếu chưa thiết lập màn hình xin phép, bạn sẽ thấy cảnh báo trong bảng điều khiển và cần phải thiết lập ngay. (Bỏ qua các bước tiếp theo nếu bạn đã thiết lập màn hình xin phép.)
Màn hình xin phép bằng Oauth
Nhấp vào "Định cấu hình màn hình xin phép" để chọn một ứng dụng "Bên ngoài" (hoặc "Nội bộ" nếu bạn là khách hàng G Suite):

Xin lưu ý rằng trong bài tập này, bạn chọn cái nào cũng được vì bạn không xuất bản mẫu lớp học lập trình. Hầu hết mọi người sẽ chọn "Bên ngoài" để chuyển đến một màn hình phức tạp hơn, nhưng bạn thực sự chỉ cần hoàn tất trường "Tên ứng dụng" ở trên cùng:

Lúc này, bạn chỉ cần tên ứng dụng, vì vậy hãy chọn một tên phản ánh lớp học lập trình mà bạn đang thực hiện, sau đó nhấp vào Lưu.
Tạo mã ứng dụng khách OAuth (xác thực tài khoản người dùng)
Bây giờ, hãy quay lại thẻ Thông tin đăng nhập để tạo mã ứng dụng khách OAuth2. Tại đây, bạn sẽ thấy nhiều mã ứng dụng OAuth mà bạn có thể tạo:

Chúng tôi đang phát triển một công cụ dòng lệnh, đó là Khác, vì vậy hãy chọn công cụ đó rồi nhấp vào nút Tạo. Chọn tên mã ứng dụng khách phản ánh ứng dụng mà bạn đang tạo hoặc chỉ cần lấy tên mặc định, thường là "Khách hàng khác N".
Lưu thông tin đăng nhập
- Một hộp thoại có thông tin đăng nhập mới sẽ xuất hiện; hãy nhấp vào OK để đóng

- Quay lại trang Thông tin xác thực, di chuyển xuống phần "Mã ứng dụng khách OAuth2", tìm và nhấp vào biểu tượng tải xuống
ở dưới cùng bên phải của mã ứng dụng khách mới tạo. 
- Thao tác này sẽ mở một hộp thoại để lưu tệp có tên
client_secret-LONG-HASH-STRING.apps.googleusercontent.com.json, có thể là vào thư mục Tải xuống. Bạn nên rút ngắn thành một tên dễ nhớ hơn nhưclient_secret.json(đây là tên mà ứng dụng mẫu sử dụng), sau đó lưu vào thư mục nơi bạn sẽ tạo ứng dụng mẫu trong lớp học lập trình này.
Tóm tắt
Giờ đây, bạn đã sẵn sàng bật các API của Google được dùng trong lớp học lập trình này. Ngoài ra, đối với tên ứng dụng trong màn hình xin phép bằng OAuth, chúng tôi đã chọn "Vision API demo" (Bản minh hoạ Vision API), vì vậy, bạn sẽ thấy tên này trong một số ảnh chụp màn hình sắp tới.
6. Bật API của Google
Lớp học lập trình này sử dụng 4 API Google Cloud, trong đó có 2 API của Google Cloud (Cloud Storage và Cloud Vision) và 2 API của Google Workspace (Google Drive và Google Trang tính). Dưới đây là hướng dẫn chung về cách bật API của Google. Sau khi bạn biết cách bật một API, các API khác cũng tương tự.
Bất kể bạn muốn sử dụng API nào của Google trong ứng dụng, bạn đều phải bật các API đó. Bạn có thể bật API từ dòng lệnh hoặc từ bảng điều khiển Cloud. Quy trình bật API là giống nhau, vì vậy, sau khi bật một API, bạn có thể bật các API khác theo cách tương tự.
Cách 1: Giao diện dòng lệnh gcloud (Cloud Shell hoặc môi trường cục bộ)
Mặc dù việc bật API từ Cloud Console phổ biến hơn, nhưng một số nhà phát triển lại thích làm mọi thứ từ dòng lệnh. Để làm như vậy, bạn cần tìm "tên dịch vụ" của một API. Có vẻ như đây là một URL: SERVICE_NAME.googleapis.com. Bạn có thể tìm thấy các sản phẩm này trong biểu đồ Sản phẩm được hỗ trợ hoặc bạn có thể truy vấn các sản phẩm này theo phương thức lập trình bằng Google Discovery API.
Với thông tin này, bằng cách sử dụng Cloud Shell (hoặc môi trường phát triển cục bộ có cài đặt công cụ dòng lệnh gcloud), bạn có thể bật một API hoặc dịch vụ như sau:
gcloud services enable SERVICE_NAME.googleapis.com
Ví dụ 1: Bật Cloud Vision API
gcloud services enable vision.googleapis.com
Ví dụ 2: Bật nền tảng điện toán không máy chủ Google App Engine
gcloud services enable appengine.googleapis.com
Ví dụ 3: Bật nhiều API bằng một yêu cầu. Ví dụ: nếu lớp học lập trình này có người xem triển khai một ứng dụng bằng Cloud Translation API cho App Engine, Cloud Functions và Cloud Run, thì dòng lệnh sẽ là:
gcloud services enable appengine.googleapis.com cloudfunctions.googleapis.com artifactregistry.googleapis.com run.googleapis.com translate.googleapis.com
Lệnh này cho phép App Engine, Cloud Functions, Cloud Run và Cloud Translation API. Ngoài ra, lệnh này còn bật Cloud Artifact Registry vì hệ thống xây dựng Cloud Build phải đăng ký hình ảnh vùng chứa tại đây để triển khai vào Cloud Run.
Ngoài ra, còn có một số lệnh để truy vấn các API cần bật hoặc những API đã được bật cho dự án của bạn.
Ví dụ 4: Truy vấn các API của Google mà bạn có thể bật cho dự án của mình
gcloud services list --available --filter="name:googleapis.com"
Ví dụ 5: Truy vấn các API của Google được bật cho dự án của bạn
gcloud services list
Để biết thêm thông tin về các lệnh trên, hãy xem tài liệu về cách bật và tắt dịch vụ và cách liệt kê dịch vụ.
Cách 2: Cloud Console
Bạn cũng có thể bật các API của Google trong Trình quản lý API. Trên Cloud Console, hãy chuyển đến API Manager (Trình quản lý API). Trên trang tổng quan này, bạn sẽ thấy một số thông tin về lưu lượng truy cập của ứng dụng, các biểu đồ cho thấy yêu cầu của ứng dụng, lỗi do ứng dụng của bạn tạo và thời gian phản hồi của ứng dụng:

Bên dưới các biểu đồ này là danh sách các API của Google được bật cho dự án của bạn:

Để bật (hoặc tắt) API, hãy nhấp vào Bật API và dịch vụ ở trên cùng:

Hoặc chuyển đến thanh điều hướng bên trái rồi chọn API và dịch vụ → Thư viện:

Dù bằng cách nào, bạn cũng sẽ truy cập được trang Thư viện API:

Nhập tên API để tìm kiếm và xem kết quả phù hợp:

Chọn API bạn muốn bật rồi nhấp vào nút Bật:

Quy trình bật tất cả API đều tương tự nhau, bất kể bạn muốn sử dụng API nào của Google.
Chi phí
Bạn có thể sử dụng nhiều API của Google mà không mất phí. Tuy nhiên, bạn sẽ phải trả phí khi sử dụng hầu hết các sản phẩm và API của Google Cloud. Khi bật Cloud API, bạn có thể được yêu cầu cung cấp một tài khoản thanh toán đang hoạt động. Tuy nhiên, một số sản phẩm của Google Cloud có bậc"Luôn miễn phí". Bạn phải vượt quá bậc này thì mới phải trả phí.
Người dùng mới của Google Cloud đủ điều kiện sử dụng Bản dùng thử miễn phí, hiện có giá trị 300 USD và dùng được trong 90 ngày đầu tiên. Các lớp học lập trình thường không phát sinh nhiều hoặc không phát sinh chi phí, vì vậy, bạn nên chờ đến khi thực sự sẵn sàng dùng thử thì mới bắt đầu dùng thử miễn phí, đặc biệt là vì đây là ưu đãi chỉ áp dụng một lần. Hạn mức của Gói miễn phí không hết hạn và áp dụng bất kể bạn có sử dụng Ưu đãi dùng thử miễn phí hay không.
Người dùng nên tham khảo thông tin về giá của mọi API trước khi bật (ví dụ: trang giá của Cloud Vision API ), đặc biệt là lưu ý xem API đó có cấp miễn phí hay không và nếu có thì cấp đó là gì. Miễn là bạn không vượt quá tổng hạn mức hằng ngày hoặc hằng tháng được chỉ định, bạn sẽ không phải trả bất kỳ khoản phí nào. Giá và các bậc miễn phí khác nhau giữa các API nhóm sản phẩm của Google. Ví dụ:
- Google Cloud – mỗi sản phẩm sẽ được tính phí theo cách khác nhau và thường là trả tiền theo mức sử dụng; hãy xem thông tin về bậc miễn phí ở trên.
- Google Maps – có một bộ API và cung cấp cho người dùng 200 USD tín dụng miễn phí mỗi tháng.
- API Google Workspace (trước đây là G Suite) – cung cấp mức sử dụng (tối đa trong một số giới hạn nhất định) được tính trong gói thuê bao hằng tháng của Google Workspace, vì vậy, bạn không phải trả phí trực tiếp khi sử dụng API cho các ứng dụng như Gmail, Google Drive, Lịch, Tài liệu, Trang tính hoặc Trang trình bày.
Các sản phẩm của Google được tính phí theo cách khác nhau, vì vậy, hãy nhớ tham khảo tài liệu phù hợp để biết thông tin đó.
Tóm tắt
Sau khi bật Cloud Vision, hãy bật 3 API còn lại (Google Drive, Cloud Storage, Google Trang tính) theo cách tương tự. Trong Cloud Shell, hãy sử dụng gcloud services enable hoặc trong bảng điều khiển Cloud:
- Quay lại Thư viện API
- Bắt đầu tìm kiếm bằng cách nhập một vài chữ cái trong tên của tệp
- Chọn API bạn muốn, rồi
- Bật
Tạo bọt, xả sạch và lặp lại. Đối với Cloud Storage, có một số lựa chọn: chọn "Google Cloud Storage JSON API". Cloud Storage API cũng sẽ yêu cầu một tài khoản thanh toán đang hoạt động.
7. Bước 0: Thiết lập quy trình nhập và mã uỷ quyền
Đây là phần đầu của một đoạn mã có kích thước trung bình, vì vậy, việc tuân theo một số phương pháp linh hoạt sẽ giúp đảm bảo có một phần cơ sở hạ tầng chung, ổn định và hoạt động trước khi giải quyết ứng dụng chính. Kiểm tra kỹ xem client_secret.json có trong thư mục hiện tại của bạn hay không, sau đó khởi động ipython và nhập đoạn mã sau hoặc lưu đoạn mã đó vào analyze_gsimg.py rồi chạy đoạn mã đó từ trình bao (cách sau được ưu tiên hơn vì chúng ta sẽ tiếp tục thêm vào mã mẫu):
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)
Thành phần cốt lõi này bao gồm các khối mã để nhập mô-đun/gói, xử lý thông tin xác thực của người dùng và tạo điểm cuối dịch vụ API. Các phần chính của mã mà bạn nên xem xét:
- Việc nhập hàm
print()giúp mẫu này tương thích với Python 2-3 và các lệnh nhập thư viện Google sẽ đưa tất cả các công cụ cần thiết để giao tiếp với API của Google. - Biến
SCOPESđại diện cho các quyền cần yêu cầu từ người dùng – hiện tại chỉ có một quyền: quyền đọc dữ liệu từ Google Drive của họ - Phần còn lại của mã xử lý thông tin đăng nhập sẽ đọc trong mã thông báo OAuth2 được lưu vào bộ nhớ đệm, có thể cập nhật thành mã truy cập mới bằng mã làm mới nếu mã truy cập ban đầu đã hết hạn.
- Nếu chưa tạo mã thông báo hoặc không truy xuất được mã truy cập hợp lệ vì một lý do khác, thì người dùng phải thực hiện quy trình 3LO (3 chân) OAuth2: tạo hộp thoại có các quyền được yêu cầu và nhắc người dùng chấp nhận. Sau khi thực hiện, ứng dụng sẽ tiếp tục, nếu không,
tools.run_flow()sẽ tạo ra một ngoại lệ và quá trình thực thi sẽ dừng lại. - Sau khi người dùng cấp quyền, một ứng dụng HTTP sẽ được tạo để giao tiếp với máy chủ và tất cả các yêu cầu đều được ký bằng thông tin đăng nhập của người dùng để đảm bảo an toàn. Sau đó, một điểm cuối dịch vụ cho API Google Drive (phiên bản 3) sẽ được tạo bằng ứng dụng HTTP đó rồi được chỉ định cho
DRIVE.
Chạy ứng dụng
Lần đầu tiên bạn thực thi tập lệnh, tập lệnh sẽ không có quyền truy cập vào các tệp của người dùng trên Drive (của bạn). Kết quả sẽ có dạng như sau khi quá trình thực thi bị tạm dừng:
$ 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
Nếu bạn đang chạy từ Cloud Shell, hãy chuyển đến phần "Từ Cloud Shell", sau đó cuộn lại để xem các màn hình có liên quan trong phần "Từ môi trường phát triển cục bộ" khi thích hợp.
Từ môi trường phát triển cục bộ
Tập lệnh dòng lệnh bị tạm dừng khi một cửa sổ trình duyệt mở ra. Bạn có thể thấy một trang cảnh báo trông đáng sợ như sau:

Đây là một mối lo ngại chính đáng vì bạn đang cố gắng chạy một ứng dụng truy cập vào dữ liệu người dùng. Vì đây chỉ là một ứng dụng minh hoạ và bạn là nhà phát triển, nên hy vọng bạn đủ tin tưởng bản thân để tiếp tục. Để hiểu rõ hơn về điều này, hãy đặt mình vào vị trí của người dùng: bạn đang được yêu cầu cho phép mã của người khác truy cập vào dữ liệu của bạn. Nếu dự định xuất bản một ứng dụng như thế này, bạn sẽ phải trải qua quy trình xác minh để người dùng không nhìn thấy màn hình này.
Sau khi nhấp vào đường liên kết "chuyển đến ứng dụng "không an toàn", bạn sẽ thấy một hộp thoại cấp quyền OAuth2 có dạng như bên dưới. Chúng tôi luôn cải thiện giao diện người dùng nên bạn không cần lo lắng nếu hộp thoại này không hoàn toàn giống như vậy:

Hộp thoại quy trình OAuth2 phản ánh các quyền mà nhà phát triển đang yêu cầu (thông qua biến SCOPES). Trong trường hợp này, đó là khả năng xem và tải xuống từ Google Drive của người dùng. Trong mã xử lý ứng dụng, các phạm vi quyền này xuất hiện dưới dạng URI, nhưng chúng được dịch sang ngôn ngữ do ngôn ngữ của người dùng chỉ định. Tại đây, người dùng phải uỷ quyền rõ ràng cho(các) quyền được yêu cầu, nếu không thì một ngoại lệ sẽ được đưa ra để tập lệnh không tiếp tục.
Bạn thậm chí có thể nhận được thêm một hộp thoại yêu cầu bạn xác nhận:

NOTE: Một số người dùng nhiều trình duyệt web và đăng nhập vào các tài khoản khác nhau. Do đó, yêu cầu uỷ quyền này có thể chuyển đến thẻ trình duyệt/cửa sổ trình duyệt không chính xác và bạn có thể phải cắt và dán đường liên kết cho yêu cầu này vào một trình duyệt đã đăng nhập bằng tài khoản chính xác.
Từ Cloud Shell
Từ Cloud Shell, không có cửa sổ trình duyệt nào bật lên, khiến bạn bị mắc kẹt. Nhận ra thông báo chẩn đoán ở dưới cùng là dành cho bạn:
If your browser is on a different machine then exit and re-run this application with the command-line parameter --noauth_local_webserver
Bạn sẽ phải nhấn tổ hợp phím ^C (Ctrl-C hoặc tổ hợp phím khác để dừng thực thi tập lệnh) và kích hoạt tập lệnh đó từ trình bao bằng cờ bổ sung. Khi chạy theo cách này, bạn sẽ nhận được đầu ra sau:
$ 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:
(Bỏ qua cảnh báo vì chúng ta biết storage.json chưa được tạo và) Làm theo hướng dẫn trong một thẻ trình duyệt khác có URL đó, bạn sẽ có trải nghiệm gần giống với những gì được mô tả ở trên cho môi trường phát triển cục bộ (xem ảnh chụp màn hình ở trên). Cuối cùng là một màn hình cuối cùng có mã xác minh để nhập vào Cloud Shell:

Sao chép và dán mã này vào cửa sổ dòng lệnh.
Tóm tắt
Ngoài "Authentication successful", bạn không nên mong đợi bất kỳ đầu ra bổ sung nào. Hãy nhớ rằng đây chỉ là bước thiết lập... bạn chưa làm gì cả. Những gì bạn đã làm là bắt đầu thành công hành trình hướng tới một điều gì đó có nhiều khả năng thực thi chính xác ngay từ lần đầu tiên. (Điều tuyệt nhất là bạn chỉ được nhắc uỷ quyền một lần; tất cả các lần thực thi tiếp theo đều bỏ qua bước này vì các quyền của bạn đã được lưu vào bộ nhớ đệm.) Bây giờ, hãy để mã thực hiện một số công việc thực tế dẫn đến đầu ra thực tế.
Khắc phục sự cố
Nếu bạn gặp lỗi thay vì không có đầu ra, thì có thể là do một hoặc nhiều nguyên nhân, chẳng hạn như nguyên nhân này:
8. Bước 1: Tải hình ảnh xuống từ Google Drive
Ở bước trước, chúng tôi đề xuất tạo mã dưới dạng analyze_gsimg.py và chỉnh sửa từ đó. Bạn cũng có thể chỉ cần cắt và dán mọi thứ trực tiếp vào iPython hoặc trình bao Python tiêu chuẩn. Tuy nhiên, cách này sẽ rườm rà hơn vì chúng ta sẽ tiếp tục xây dựng ứng dụng từng phần.
Giả sử ứng dụng của bạn đã được uỷ quyền và điểm cuối dịch vụ API đã được tạo. Trong mã của bạn, biến này được biểu thị bằng biến DRIVE. Bây giờ, hãy tìm một tệp hình ảnh trên Google Drive của bạn và
đặt biến đó thành NAME. Nhập mã đó cùng với hàm drive_get_img() sau đây ngay bên dưới mã ở Bước 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
Tập hợp files() của Drive có một phương thức list() thực hiện một truy vấn (tham số q) cho tệp được chỉ định. Tham số fields được dùng để chỉ định những giá trị trả về mà bạn quan tâm. Tại sao bạn lại phải lấy mọi thứ và làm chậm quá trình nếu bạn không quan tâm đến các giá trị khác? Nếu bạn mới sử dụng mặt nạ trường để lọc các giá trị trả về của API, hãy xem bài đăng trên blog và video này. Nếu không, hãy thực thi truy vấn và lấy thuộc tính files được trả về, mặc định là một mảng danh sách trống nếu không có kết quả trùng khớp.
Nếu không có kết quả nào, phần còn lại của hàm sẽ bị bỏ qua và None sẽ được trả về (một cách ngầm định). Nếu không, hãy lấy phản hồi trùng khớp đầu tiên (rsp[0]), trả về tên tệp, MIMEtype, dấu thời gian sửa đổi gần đây nhất và cuối cùng là tải trọng nhị phân của tệp đó, được truy xuất bằng hàm get_media() (thông qua mã nhận dạng tệp), cũng trong bộ sưu tập files(). (Tên phương thức có thể khác một chút so với các thư viện ứng dụng bằng ngôn ngữ khác.)
Phần cuối cùng là phần nội dung "main" (chính) điều khiển toàn bộ ứng dụng:
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)
Giả sử có một hình ảnh tên là section-work-card-img_2x.jpg trên Drive và được đặt thành FILE, sau khi thực thi tập lệnh thành công, bạn sẽ thấy đầu ra xác nhận rằng tập lệnh có thể đọc tệp từ Drive (nhưng không lưu vào máy tính):
$ python3 analyze_gsimg.py Downloaded 'section-work-card-img_2x.jpg' (image/jpeg, 2020-02-27T09:27:22.095Z, size: 27781)
Khắc phục sự cố
Nếu bạn không nhận được kết quả thành công như trên, thì có thể là do một hoặc nhiều nguyên nhân, chẳng hạn như nguyên nhân này:
Tóm tắt
Trong phần này, bạn đã tìm hiểu cách kết nối với Drive API (trong 2 lệnh gọi API riêng biệt) để truy vấn một tệp cụ thể rồi tải tệp đó xuống. Trường hợp sử dụng cho doanh nghiệp: lưu trữ dữ liệu trên Drive và có thể phân tích dữ liệu đó, chẳng hạn như bằng các công cụ của Google Cloud. Mã cho ứng dụng của bạn ở giai đoạn này phải khớp với mã trong kho lưu trữ tại step1-drive/analyze_gsimg.py.
Đọc thêm về cách tải tệp xuống trên Google Drive tại đây hoặc xem bài đăng này trên blog và video này. Phần này của lớp học lập trình gần giống với toàn bộ lớp học lập trình giới thiệu về API Google Workspace – thay vì tải một tệp xuống, phần này sẽ hiển thị 100 tệp/thư mục đầu tiên trên Google Drive của người dùng và sử dụng một phạm vi hạn chế hơn.
9. Bước 2: Lưu trữ tệp vào Cloud Storage
Bước tiếp theo là thêm chế độ hỗ trợ cho Google Cloud Storage. Để làm việc này, chúng ta cần nhập một gói Python khác là io. Đảm bảo phần trên cùng của các lệnh nhập hiện có dạng như sau:
from __future__ import print_function
import io
Ngoài tên tệp trên Drive, chúng tôi cần một số thông tin về vị trí lưu trữ tệp này trên Cloud Storage, cụ thể là tên "nhóm" mà bạn sẽ đặt tệp vào và(các) tiền tố "thư mục mẹ". Chúng ta sẽ nói thêm về vấn đề này sau đây:
FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = '' # YOUR IMG FILE PREFIX
Về bộ chứa: Cloud Storage cung cấp bộ nhớ blob vô định hình. Khi tải tệp lên, công cụ này không hiểu khái niệm về loại tệp, phần mở rộng, v.v. như Google Drive. Chúng chỉ là "blob" đối với Cloud Storage. Ngoài ra, Cloud Storage không có khái niệm về thư mục hoặc thư mục con.
Có, bạn có thể dùng dấu gạch chéo (/) trong tên tệp để biểu thị sự trừu tượng của nhiều thư mục con, nhưng cuối cùng, tất cả các BLOB của bạn sẽ được đưa vào một vùng chứa và "/" chỉ là các ký tự trong tên tệp. Hãy xem trang quy ước đặt tên cho vùng lưu trữ và đối tượng để biết thêm thông tin.
Bước 1 ở trên yêu cầu phạm vi chỉ đọc của Drive. Vào thời điểm đó, đó là tất cả những gì bạn cần. Giờ đây, bạn cần có quyền tải lên (đọc-ghi) đối với Cloud Storage. Thay đổi SCOPES từ một biến chuỗi duy nhất thành một mảng (bộ dữ liệu [hoặc danh sách] Python) gồm các phạm vi quyền để có dạng như sau:
SCOPES = (
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/devstorage.full_control',
)
Bây giờ, hãy tạo một điểm cuối dịch vụ cho Cloud Storage ngay bên dưới điểm cuối dịch vụ cho Drive. Xin lưu ý rằng chúng tôi đã thay đổi một chút lệnh gọi để sử dụng lại cùng một đối tượng máy khách HTTP vì không cần tạo đối tượng mới khi đối tượng đó có thể là một tài nguyên dùng chung.
# create API service endpoints
HTTP = creds.authorize(Http())
DRIVE = discovery.build('drive', 'v3', http=HTTP)
GCS = discovery.build('storage', 'v1', http=HTTP)
Bây giờ, hãy thêm hàm này (sau drive_get_img()) để tải lên 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()
Lệnh gọi objects.().insert() yêu cầu tên nhóm, siêu dữ liệu tệp và chính blob nhị phân. Để lọc các giá trị trả về, biến fields chỉ yêu cầu tên đối tượng và tên nhóm được trả về từ API. Để tìm hiểu thêm về mặt nạ trường trong các yêu cầu đọc API, hãy xem bài đăng và video này.
Giờ thì hãy tích hợp việc sử dụng gcs_blob_upload() vào ứng dụng chính:
# 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)
Biến gcsname hợp nhất mọi(các) tên "thư mục con mẹ" được thêm vào tên tệp và khi được thêm tiền tố bằng tên nhóm, sẽ tạo ấn tượng rằng bạn đang lưu trữ tệp tại "/bucket/parent.../filename". Hãy chèn đoạn mã này ngay sau hàm print() đầu tiên ngay phía trên mệnh đề else để toàn bộ "main" trông như sau:
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)
Giả sử chúng ta chỉ định một nhóm có tên là "vision-demo" với "analyzed_imgs" làm "thư mục con mẹ". Sau khi bạn đặt các biến đó và chạy lại tập lệnh, section-work-card-img_2x.jpg sẽ được tải xuống từ Drive rồi tải lên Cloud Storage, đúng không? KHÔNG!
$ 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">
Hãy xem kỹ, mặc dù quá trình tải xuống từ Drive đã thành công, nhưng quá trình tải lên Cloud Storage lại thất bại. Tại sao?
Lý do là khi uỷ quyền cho ứng dụng này ở Bước 1, chúng ta chỉ uỷ quyền truy cập ở chế độ chỉ đọc vào Google Drive. Mặc dù đã thêm phạm vi đọc-ghi cho Cloud Storage, nhưng chúng tôi chưa bao giờ nhắc người dùng uỷ quyền truy cập đó. Để khắc phục, chúng ta cần xoá tệp storage.json bị thiếu phạm vi này và chạy lại.
Sau khi bạn uỷ quyền lại (xác nhận điều này bằng cách xem bên trong storage.json và thấy cả hai phạm vi ở đó), kết quả đầu ra của bạn sẽ như mong đợi:
$ 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'
Tóm tắt
Đây là một vấn đề lớn, cho bạn thấy cách chuyển tệp giữa cả hai hệ thống lưu trữ dựa trên đám mây chỉ bằng một vài dòng mã. Trường hợp sử dụng cho doanh nghiệp ở đây là sao lưu một tài nguyên có thể bị hạn chế vào bộ nhớ "lạnh" và rẻ hơn như đã đề cập trước đó. Cloud Storage cung cấp các lớp lưu trữ khác nhau tuỳ thuộc vào việc bạn truy cập vào dữ liệu của mình thường xuyên, hằng tháng, hằng quý hay hằng năm.
Tất nhiên, đôi khi các nhà phát triển cũng hỏi chúng tôi lý do tồn tại cả Google Drive và Cloud Storage. Rốt cuộc, chẳng phải cả hai đều là bộ nhớ tệp trên đám mây sao? Đó là lý do chúng tôi tạo ra video này. Mã của bạn ở giai đoạn này phải khớp với mã trong kho lưu trữ tạistep2-gcs/analyze_gsimg.py.
10. Bước 3: Phân tích bằng Cloud Vision
Mặc dù hiện tại chúng ta biết rằng bạn có thể di chuyển dữ liệu giữa Google Cloud và Google Workspace, nhưng chúng ta chưa phân tích gì cả. Vì vậy, đã đến lúc gửi hình ảnh đến Cloud Vision để chú thích nhãn, hay còn gọi là phát hiện đối tượng. Để làm như vậy, chúng ta cần mã hoá dữ liệu bằng Base64, tức là một mô-đun Python khác, base64. Đảm bảo phần nhập ở trên cùng của bạn hiện có dạng như sau:
from __future__ import print_function
import base64
import io
Theo mặc định, Vision API sẽ trả về tất cả nhãn mà API tìm thấy. Để đảm bảo tính nhất quán, hãy chỉ yêu cầu 5 kết quả hàng đầu (tất nhiên là người dùng có thể điều chỉnh). Chúng ta sẽ sử dụng một biến hằng số TOP cho việc này; hãy thêm biến này bên dưới tất cả các hằng số khác:
FILE = 'YOUR_IMG_ON_DRIVE'
BUCKET = 'YOUR_BUCKET_NAME'
PARENT = '' # YOUR IMG FILE PREFIX
TOP = 5 # TOP # of VISION LABELS TO SAVE
Tương tự như các bước trước, chúng ta cần một phạm vi quyền khác, lần này là cho Vision API. Cập nhật SCOPES bằng chuỗi của:
SCOPES = (
'https://www.googleapis.com/auth/drive.readonly',
'https://www.googleapis.com/auth/devstorage.full_control',
'https://www.googleapis.com/auth/cloud-vision',
)
Bây giờ, hãy tạo một điểm cuối dịch vụ cho Cloud Vision để điểm cuối này khớp với các điểm cuối khác như sau:
# 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)
Giờ đây, hãy thêm hàm này để gửi tải trọng hình ảnh đến 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'])
Lệnh gọi images().annotate() yêu cầu dữ liệu cộng với các tính năng API mong muốn. Giới hạn 5 nhãn hàng đầu cũng là một phần của tải trọng (nhưng hoàn toàn không bắt buộc). Nếu lệnh gọi thành công, tải trọng sẽ trả về 5 nhãn hàng đầu của các đối tượng cùng với điểm tin cậy của một đối tượng trong hình ảnh. (Nếu không có phản hồi, hãy chỉ định một từ điển Python trống để câu lệnh if sau đây không bị lỗi.) Hàm này chỉ đơn giản là đối chiếu dữ liệu đó thành một chuỗi CSV để sử dụng trong báo cáo của chúng ta.
5 dòng gọi vision_label_img() này phải được đặt ngay sau khi tải lên Cloud Storage thành công:
# 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)
Sau khi thêm, toàn bộ trình điều khiển chính sẽ có dạng như sau:
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)
Việc xoá storage.json để làm mới các phạm vi và chạy lại ứng dụng đã cập nhật sẽ cho ra kết quả tương tự như sau, lưu ý rằng đã thêm tính năng phân tích bằng 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
Tóm tắt
Không phải ai cũng có chuyên môn về học máy để tạo và huấn luyện các mô hình học máy của riêng họ nhằm phân tích dữ liệu. Nhóm Google Cloud đã cung cấp một số mô hình được huấn luyện trước của Google để sử dụng cho mục đích chung và đặt chúng sau các API, giúp dân chủ hoá AI và học máy cho mọi người.
Nếu là nhà phát triển và có thể gọi một API, bạn có thể sử dụng học máy. Cloud Vision chỉ là một trong những dịch vụ API mà bạn có thể dùng để phân tích dữ liệu. Tìm hiểu về những thông tin khác tại đây. Mã của bạn hiện phải khớp với mã trong kho lưu trữ tạistep3-vision/analyze_gsimg.py.
11. Bước 4: Tạo báo cáo bằng Google Trang tính
Đến thời điểm này, bạn đã có thể lưu trữ và phân tích dữ liệu của công ty, nhưng điều còn thiếu là bản tóm tắt về công việc này. Hãy sắp xếp tất cả kết quả vào một báo cáo duy nhất mà bạn có thể đưa cho sếp. Có gì dễ trình bày cho ban quản lý hơn một bảng tính?
Bạn không cần nhập thêm cho API Google Trang tính và thông tin mới duy nhất cần thiết là mã nhận dạng tệp của một bảng tính hiện có đã được định dạng và đang chờ một hàng dữ liệu mới, do đó có hằng số SHEET. Bạn nên tạo một bảng tính mới có dạng như sau:

URL của bảng tính đó sẽ có dạng như sau: https://docs.google.com/spreadsheets/d/FILE_ID/edit. Lấy FILE_ID đó rồi chỉ định làm chuỗi cho SHEET.
Chúng ta cũng đã thêm một hàm nhỏ có tên là k_ize() để chuyển đổi byte thành kilobyte, xác định hàm này là lambda của Python vì đây là một hàm đơn giản. Cả hai đều được tích hợp với các hằng số khác như sau:
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
Tương tự như các bước trước, chúng ta cần một phạm vi quyền khác, lần này là quyền đọc-ghi cho API Trang tính. SCOPES hiện có cả 4 thuộc tính cần thiết:
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',
)
Bây giờ, hãy tạo một điểm cuối dịch vụ cho Google Trang tính gần các điểm cuối khác để có dạng như sau:
# 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)
Chức năng của sheet_append_row() rất đơn giản: lấy một hàng dữ liệu và mã nhận dạng của Trang tính, sau đó thêm hàng đó vào Trang tính đó:
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')
Lệnh gọi spreadsheets().values().append() yêu cầu mã nhận dạng tệp của Trang tính, một dải ô, cách nhập dữ liệu và chính dữ liệu đó. Mã nhận dạng tệp rất đơn giản, phạm vi ô được cung cấp theo ký hiệu A1. Phạm vi "Sheet1" có nghĩa là toàn bộ Trang tính. Điều này báo hiệu cho API biết rằng bạn muốn thêm hàng sau tất cả dữ liệu trong Trang tính. Có hai lựa chọn về cách thêm dữ liệu vào Trang tính, "RAW" (nhập dữ liệu chuỗi theo đúng nghĩa đen) hoặc "USER_ENTERED" (ghi dữ liệu như thể người dùng đã nhập dữ liệu đó trên bàn phím bằng ứng dụng Google Trang tính, giữ nguyên mọi tính năng định dạng ô).
Nếu lệnh gọi thành công, giá trị trả về sẽ không thực sự hữu ích. Vì vậy, chúng ta chọn lấy số lượng ô được cập nhật theo yêu cầu API. Dưới đây là mã gọi hàm đó:
# 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 Trang tính có các cột biểu thị dữ liệu, chẳng hạn như mọi "thư mục con" mẹ, vị trí của tệp được lưu trữ trên Cloud Storage (thùng chứa + tên tệp), MIMEtype của tệp, kích thước tệp (ban đầu tính bằng byte, nhưng được chuyển đổi thành kilobyte bằng k_ize()) và chuỗi nhãn Cloud Vision. Ngoài ra, hãy lưu ý rằng vị trí được lưu trữ là một siêu liên kết để người quản lý có thể nhấp vào để xác nhận rằng vị trí đó đã được sao lưu an toàn.
Sau khi thêm khối mã ở trên ngay sau khi hiển thị kết quả từ Cloud Vision, phần chính điều khiển ứng dụng hiện đã hoàn tất, mặc dù có cấu trúc hơi phức tạp:
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)
Xoá storage.json lần cuối và chạy lại ứng dụng đã cập nhật sẽ cho ra kết quả tương tự như sau, lưu ý rằng đã thêm tính năng phân tích bằng 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
Mặc dù hữu ích, nhưng dòng đầu ra bổ sung sẽ được trực quan hoá tốt hơn bằng cách xem nhanh Google Trang tính đã cập nhật, với dòng cuối cùng (hàng 7 trong ví dụ bên dưới) được thêm vào tập dữ liệu hiện có đã được thêm trước đó:

Tóm tắt
Trong 3 bước đầu tiên của hướng dẫn này, bạn đã kết nối với Google Workspace và Google Cloud API để di chuyển dữ liệu và phân tích dữ liệu đó, chiếm 80% tổng số công việc. Tuy nhiên, cuối cùng, tất cả những điều này sẽ không có ý nghĩa gì nếu bạn không thể trình bày cho ban quản lý tất cả những gì bạn đã đạt được. Để hình dung rõ hơn về kết quả, việc tóm tắt tất cả kết quả trong một báo cáo được tạo sẽ mang lại nhiều thông tin.
Để nâng cao hơn nữa tính hữu ích của hoạt động phân tích, ngoài việc ghi kết quả vào bảng tính, một điểm cải tiến có thể có là lập chỉ mục 5 nhãn hàng đầu này cho mỗi hình ảnh để có thể tạo một cơ sở dữ liệu nội bộ cho phép nhân viên được uỷ quyền truy vấn hình ảnh theo nhóm tìm kiếm, nhưng chúng tôi sẽ để phần này cho độc giả tự thực hiện.
Hiện tại, kết quả của chúng tôi nằm trong một Trang tính và ban quản lý có thể truy cập vào Trang tính này. Mã cho ứng dụng của bạn ở giai đoạn này phải khớp với mã trong kho lưu trữ tại step4-sheets/analyze_gsimg.py. Bước cuối cùng là dọn dẹp mã và biến mã đó thành một tập lệnh có thể sử dụng.
12. *Bước cuối cùng: tái cấu trúc
(không bắt buộc) Ứng dụng hoạt động là điều tốt, nhưng chúng ta có thể cải thiện ứng dụng này không? Có, đặc biệt là ứng dụng chính có vẻ như một mớ hỗn độn. Hãy đưa điều đó vào hàm riêng và điều khiển hàm đó để cho phép hoạt động đầu vào của người dùng thay vì các hằng số cố định. Chúng ta sẽ thực hiện việc đó bằng mô-đun argparse. Hơn nữa, hãy mở một thẻ trình duyệt web để hiển thị Trang tính sau khi chúng ta ghi hàng dữ liệu vào đó. Bạn có thể thực hiện việc này bằng mô-đun webbrowser. Kết hợp các lệnh nhập này với các lệnh nhập khác để các lệnh nhập hàng đầu trông như sau:
from __future__ import print_function
import argparse
import base64
import io
import webbrowser
Để có thể sử dụng mã này trong các ứng dụng khác, chúng ta cần có khả năng ngăn chặn đầu ra. Vì vậy, hãy thêm cờ DEBUG để thực hiện việc đó, bằng cách thêm dòng này vào cuối phần hằng số ở gần đầu:
DEBUG = False
Bây giờ, hãy nói về phần nội dung chính. Khi chúng tôi tạo mẫu này, bạn có thể bắt đầu cảm thấy "không thoải mái" khi mã của chúng tôi thêm một cấp độ lồng ghép khác với mỗi dịch vụ được thêm. Nếu cảm thấy như vậy, bạn không phải là người duy nhất, vì điều này làm tăng độ phức tạp của mã như mô tả trong bài đăng này trên Blog kiểm thử của Google.
Theo phương pháp hay nhất này, hãy sắp xếp lại phần chính của ứng dụng thành một hàm và return tại mỗi "điểm ngắt" thay vì lồng (trả về None nếu có bước nào đó không thành công và True nếu tất cả đều thành công):
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
Điều này giúp mã nguồn gọn gàng và rõ ràng hơn, loại bỏ cảm giác về chuỗi if-else đệ quy, đồng thời giảm độ phức tạp của mã như mô tả ở trên. Mảnh ghép cuối cùng là tạo một trình điều khiển chính "thực", cho phép người dùng tuỳ chỉnh và giảm thiểu đầu ra (trừ phi muốn):
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)
Nếu tất cả các bước đều thành công, tập lệnh sẽ khởi chạy một trình duyệt web đến bảng tính được chỉ định nơi hàng dữ liệu mới được thêm vào.
Tóm tắt
Không cần xoá storage.json vì không có thay đổi nào về phạm vi. Chạy lại ứng dụng đã cập nhật sẽ cho thấy một cửa sổ trình duyệt mới mở ra cho Trang tính đã sửa đổi, ít dòng đầu ra hơn và việc đưa ra lựa chọn -h sẽ cho người dùng thấy các lựa chọn của họ, bao gồm cả -v để khôi phục các dòng đầu ra hiện bị chặn mà họ đã thấy trước đó:
$ 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
Các lựa chọn khác cho phép người dùng chọn tên tệp Drive, "thư mục con" và tên bộ chứa Cloud Storage, "N" kết quả hàng đầu từ Cloud Vision và mã nhận dạng tệp bảng tính (Sheets) khác. Với những bản cập nhật cuối cùng này, phiên bản cuối cùng của mã hiện phải khớp với nội dung trong kho lưu trữ tạifinal/analyze_gsimg.py cũng như tại đây, trong toàn bộ nội dung:
'''
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)
Chúng tôi sẽ cố gắng hết sức để nội dung của hướng dẫn này luôn được cập nhật, nhưng đôi khi kho lưu trữ sẽ có phiên bản mã mới nhất.
13. Xin chúc mừng!
Chắc chắn bạn đã học được rất nhiều điều trong lớp học lập trình này và bạn đã hoàn thành một trong những lớp học lập trình dài hơn. Do đó, bạn đã giải quyết một trường hợp có thể xảy ra trong doanh nghiệp bằng khoảng 130 dòng mã Python, tận dụng tất cả các dịch vụ của Google Cloud và Google Workspace, đồng thời di chuyển dữ liệu giữa các dịch vụ này để xây dựng một giải pháp hoạt động. Bạn có thể khám phá kho lưu trữ nguồn mở cho tất cả các phiên bản của ứng dụng này (xem thêm thông tin bên dưới).
Dọn dẹp
- Việc sử dụng Google Cloud API không miễn phí, trong khi API Google Workspace được tính vào Gói thuê bao của Google Workspace hằng tháng (người dùng Gmail cá nhân không phải trả phí hằng tháng), nên người dùng Google Workspace không cần dọn dẹp/ngừng sử dụng API. Đối với Google Cloud, bạn có thể chuyển đến bảng điều khiển Cloud và kiểm tra "thẻ" Thanh toán để xem các khoản phí ước tính.
- Đối với Cloud Vision, bạn được phép thực hiện một số lượng lệnh gọi API cố định mỗi tháng mà không mất phí. Vì vậy, miễn là bạn không vượt quá những giới hạn đó, bạn không cần phải tắt bất cứ thứ gì cũng như không bắt buộc phải tắt/xoá dự án của mình. Bạn có thể xem thêm thông tin về hạn mức miễn phí và phí của Vision API trên trang định giá của API này.
- Một số người dùng Cloud Storage được cấp một lượng bộ nhớ miễn phí mỗi tháng. Nếu những hình ảnh bạn lưu trữ bằng lớp học lập trình này không khiến bạn vượt quá hạn mức đó, thì bạn sẽ không phải trả phí. Bạn có thể xem thêm thông tin về việc lập hoá đơn và hạn mức miễn phí của GCS trên trang định giá của dịch vụ này. Bạn có thể xem và dễ dàng xoá các blob trong trình duyệt Cloud Storage.
- Việc sử dụng Google Drive cũng có thể có hạn mức bộ nhớ. Nếu vượt quá hạn mức này (hoặc gần vượt quá), bạn có thể cân nhắc sử dụng công cụ mà bạn đã tạo trong lớp học lập trình này để lưu trữ những hình ảnh đó vào Cloud Storage nhằm có thêm dung lượng trên Drive. Bạn có thể xem thêm thông tin về Bộ nhớ Google Drive trên trang thông tin về giá tương ứng dành cho người dùng Google Workspace Basic hoặc người dùng Gmail/người tiêu dùng.
Mặc dù hầu hết các gói Google Workspace Business và Enterprise đều có bộ nhớ không giới hạn, nhưng điều này có thể khiến các thư mục trên Drive của bạn trở nên lộn xộn và/hoặc quá tải. Ứng dụng mà bạn đã tạo trong hướng dẫn này là một cách tuyệt vời để lưu trữ các tệp không cần thiết và dọn dẹp Google Drive.
Phiên bản thay thế
Mặc dù final/analyze_gsimg.py là phiên bản chính thức "mới nhất" mà bạn đang sử dụng trong hướng dẫn này, nhưng câu chuyện chưa kết thúc. Một vấn đề với phiên bản cuối cùng của ứng dụng là ứng dụng này sử dụng các thư viện uỷ quyền cũ đã ngừng hoạt động. Chúng tôi chọn cách này vì tại thời điểm viết bài này, các thư viện uỷ quyền mới hơn không hỗ trợ một số phần tử chính: quản lý bộ nhớ mã thông báo OAuth và độ an toàn của luồng.
Thư viện uỷ quyền hiện tại (mới hơn)
Tuy nhiên, đến một thời điểm nào đó, các thư viện uỷ quyền cũ sẽ không còn được hỗ trợ nữa. Vì vậy, bạn nên xem xét các phiên bản sử dụng thư viện uỷ quyền mới hơn (hiện tại) trong thư mục alt của kho lưu trữ ngay cả khi các phiên bản đó không an toàn cho luồng (nhưng bạn có thể tạo giải pháp của riêng mình). Tìm những tệp có biểu tượng *newauth* trong tên.
Thư viện ứng dụng sản phẩm của Google Cloud
Google Cloud khuyến nghị tất cả nhà phát triển sử dụng thư viện ứng dụng sản phẩm khi dùng Cloud APIs của Google. Rất tiếc, các API không phải của Google Cloud hiện không có những thư viện như vậy. Việc sử dụng các thư viện cấp thấp cho phép sử dụng API nhất quán và có khả năng đọc tốt hơn. Tương tự như đề xuất ở trên, các phiên bản thay thế sử dụng thư viện ứng dụng sản phẩm Google Cloud có trong thư mục alt của kho lưu trữ để bạn xem xét. Tìm những tệp có biểu tượng *-gcp* trong tên.
Uỷ quyền tài khoản dịch vụ
Khi chỉ làm việc trên đám mây, thường sẽ không có người dùng cũng như dữ liệu do người dùng (là con người) sở hữu. Vì vậy, đó là lý do tại sao tài khoản dịch vụ và uỷ quyền tài khoản dịch vụ chủ yếu được dùng với Google Cloud. Tuy nhiên, các tài liệu trên Google Workspace thường thuộc sở hữu của người dùng (là con người), vì vậy, đó là lý do hướng dẫn này sử dụng hoạt động uỷ quyền tài khoản người dùng. Điều đó không có nghĩa là bạn không thể sử dụng API Google Workspace với tài khoản dịch vụ. Chỉ cần có cấp truy cập phù hợp, bạn chắc chắn có thể sử dụng những tài khoản đó trong các ứng dụng. Tương tự như trên, các phiên bản thay thế sử dụng uỷ quyền tài khoản dịch vụ có trong thư mục alt của kho lưu trữ để bạn xem xét. Tìm những tệp có biểu tượng *-svc* trong tên.
Danh mục phiên bản thay thế
Dưới đây, bạn sẽ thấy tất cả các phiên bản thay thế của final/analyze_gsimg.py, mỗi phiên bản có một hoặc nhiều thuộc tính nêu trên. Trong tên tệp của mỗi phiên bản, hãy tìm:
- "
oldauth" cho các phiên bản sử dụng thư viện xác thực cũ (ngoàifinal/analyze_gsimg.py) - "
newauth" cho những người dùng thư viện uỷ quyền hiện tại/mới hơn - "
gcp" cho những người dùng thư viện ứng dụng sản phẩm Google Cloud, tức là google-cloud-storage, v.v. - "
svc" cho những người sử dụng phương thức uỷ quyền tài khoản dịch vụ ("svc acct") thay vì tài khoản người dùng
Sau đây là tất cả các phiên bản:
Tên tệp | Mô tả |
| Mẫu chính; sử dụng các thư viện uỷ quyền cũ |
| Tương tự như |
| Tương tự như |
| Tương tự như |
| Tương tự như |
| Tương tự như |
| Tương tự như |
| Tương tự như |
Kết hợp với final/analyze_gsimg.py ban đầu , bạn sẽ có tất cả các tổ hợp có thể có của giải pháp cuối cùng, bất kể môi trường phát triển Google API của bạn là gì, và có thể chọn tổ hợp phù hợp nhất với nhu cầu của bạn. Bạn cũng có thể xem alt/README.md để biết nội dung giải thích tương tự.
Nghiên cứu bổ sung
Dưới đây là một vài ý tưởng về cách bạn có thể thực hiện bài tập này thêm một hoặc hai bước nữa. Bạn có thể mở rộng tập hợp vấn đề mà giải pháp hiện tại có thể xử lý, cho phép bạn thực hiện những điểm cải tiến sau:
- (nhiều hình ảnh trong thư mục) Thay vì xử lý một hình ảnh, giả sử bạn có hình ảnh trong thư mục trên Google Drive.
- (nhiều hình ảnh trong tệp ZIP) Thay vì một thư mục chứa hình ảnh, bạn có thể dùng tệp lưu trữ ZIP chứa các tệp hình ảnh không? Nếu bạn đang dùng Python, hãy cân nhắc sử dụng mô-đun
zipfile. - (phân tích nhãn Vision) Nhóm các hình ảnh tương tự với nhau, có thể bắt đầu bằng cách tìm nhãn phổ biến nhất, sau đó là nhãn phổ biến thứ hai, v.v.
- (tạo biểu đồ) Câu hỏi tiếp theo số 3, tạo biểu đồ bằng API Trang tính dựa trên kết quả phân tích và phân loại của Vision API
- (phân loại tài liệu) Thay vì phân tích hình ảnh bằng Cloud Vision API, giả sử bạn có các tệp PDF cần phân loại bằng Cloud Natural Language API. Bằng cách sử dụng các giải pháp ở trên, những tệp PDF này có thể nằm trong các thư mục trên Drive hoặc tệp lưu trữ ZIP trên Drive.
- (tạo bản trình bày) Sử dụng Slides API để tạo một bộ trang trình bày từ nội dung của báo cáo trên Google Trang tính. Để tìm ý tưởng, hãy xem bài đăng trên blog và video này về cách tạo trang trình bày từ dữ liệu trong bảng tính.
- (xuất dưới dạng PDF) Xuất bảng tính và/hoặc trang trình bày dưới dạng PDF, tuy nhiên đây không phải là tính năng của API Trang tính hay API Trang trình bày. Gợi ý: API Google Drive. Điểm cộng: hợp nhất cả tệp PDF của Trang tính và Trang trình bày thành một tệp PDF chính bằng các công cụ như Ghostscript (Linux, Windows) hoặc
Combine PDF Pages.action(Mac OS X).
Tìm hiểu thêm
Lớp học lập trình
- Giới thiệu về các API Google Workspace (API Google Drive) (Python)
- Sử dụng Cloud Vision với Python (Python)
- Tạo công cụ báo cáo tuỳ chỉnh (API Google Trang tính) (JS/Node)
- Tải các đối tượng lên Google Cloud Storage (không cần viết mã)
Giải pháp chung
Google Workspace
- Trang chủ của API Google Drive
- Trang chủ của API Google Trang tính
- Tổng quan và tài liệu dành cho nhà phát triển Google Workspace
Google Cloud
- Trang chủ Google Cloud Storage
- Trang chủ và bản minh hoạ trực tiếp của Google Cloud Vision
- Tài liệu về Cloud Vision API
- Tài liệu về tính năng gắn nhãn hình ảnh của Vision API
- Python trên Google Cloud
- Thư viện ứng dụng sản phẩm của Google Cloud
- Tài liệu về Google Cloud
Giấy phép
Tác phẩm này được cấp phép theo giấy phép Ghi công theo Creative Commons 2.0 Chung.