Tự động hóa Google Search Console API bằng Python: Hướng dẫn kéo dữ liệu, quota và cảnh báo
Tự động hóa Google Search Console API bằng Python: xác thực service account, kéo dữ liệu hằng ngày, xử lý quota, kiểm tra URL và cảnh báo sụt giảm.
Long Nguyen
Lập trình viên Fullstack · Kỹ sư AI · Nhà nghiên cứu
Search Console API có thể và không thể tự động hóa những gì?
Search Console API là giao diện chủ yếu để đọc bốn nhóm dữ liệu: hiệu suất, kiểm tra URL, sitemap và danh sách các property bạn sở hữu. API không thể buộc Google lập chỉ mục các trang thông thường, cũng không cung cấp mọi báo cáo bạn thấy trên giao diện web. Trước khi viết code, hãy đối chiếu từng tác vụ muốn tự động hóa với đúng endpoint hỗ trợ tác vụ đó.
| Tác vụ | Nên dùng | Giới hạn cứng cần tính đến |
|---|---|---|
| Clicks, impressions, CTR và vị trí hằng ngày theo trang hoặc truy vấn | searchAnalytics.query |
25.000 dòng mỗi request; 50.000 dòng mỗi ngày cho mỗi loại tìm kiếm |
| Kiểm tra URL đã được lập chỉ mục chưa, canonical nào được chọn và lần crawl gần nhất | urlInspection.index.inspect |
2.000 truy vấn mỗi ngày cho mỗi site |
| Gửi hoặc liệt kê sitemap | sitemaps.submit / sitemaps.list |
Cần scope đọc/ghi |
| Lưu toàn bộ lịch sử hiệu suất vào data warehouse | Xuất hàng loạt sang BigQuery | Bao gồm mọi dữ liệu, ngoại trừ truy vấn ẩn danh |
| Yêu cầu Google crawl ngay một trang thông thường | Không hỗ trợ | Indexing API chỉ áp dụng cho trang tuyển dụng và trang livestream |
Dòng cuối cùng là nơi phần lớn dự án tự động hóa thất bại bắt đầu: họ lên kế hoạch chạy script mỗi đêm để đẩy mọi bài viết mới lên Google, rồi phát hiện không có endpoint được hỗ trợ nào làm việc đó với các trang thông thường. Phần 7 sẽ giải thích rõ hơn.
Xác thực: dùng service account hay OAuth cho tác vụ chạy tự động?
Mọi request đều phải kèm token OAuth 2.0; API key không cấp quyền truy cập dữ liệu property riêng tư. Google định nghĩa hai scope: webmasters.readonly cho quyền chỉ đọc và webmasters cho quyền đọc/ghi. Hãy dùng scope chỉ đọc cho các tác vụ báo cáo, chỉ thêm quyền ghi cho script gửi sitemap.
Với tác vụ chạy theo lịch mà không có người theo dõi, service account là lựa chọn thực tế hơn. Luồng OAuth cần người dùng chấp thuận qua trình duyệt và refresh token; nếu refresh token được cấp khi màn hình xin consent vẫn ở trạng thái thử nghiệm, token sẽ hết hạn sau khoảng một tuần, khiến tác vụ ngừng chạy mà bạn không hay biết.
- Trong Google Cloud, tạo một project và bật Search Console API.
- Tạo service account và tải xuống JSON key. Hãy bảo vệ key này như mật khẩu.
- Trong Search Console, mở Settings, chọn Users and permissions, rồi thêm email của service account làm người dùng trên từng property mà tác vụ cần truy cập. Cấp mức quyền thấp nhất nhưng vẫn đủ cho tác vụ.
- Sử dụng chính xác mã property như Search Console hiển thị:
https://www.example.com/cho property dạng URL-prefix hoặcsc-domain:example.comcho property dạng Domain.
from google.oauth2 import service_account
from googleapiclient.discovery import build
SCOPES = ['https://www.googleapis.com/auth/webmasters.readonly']
creds = service_account.Credentials.from_service_account_file(
'service-account.json', scopes=SCOPES)
gsc = build('searchconsole', 'v1', credentials=creds)
print(gsc.sites().list().execute()) # properties this account can see
Nếu sites().list() trả về danh sách rỗng, việc xác thực đã thành công nhưng service account chưa được thêm vào property nào. Bật API trong cloud project là chưa đủ; quyền truy cập được cấp cho từng property bên trong Search Console. Đây là nguyên nhân phổ biến nhất dẫn đến lỗi 403 trong các hệ thống mới thiết lập.
Dùng Python kéo dữ liệu Search Console vượt giới hạn 25.000 dòng
Tham số rowLimit nhận giá trị từ 1 đến 25.000 và mặc định là 1.000, vì vậy nếu bỏ qua tham số này, request sẽ âm thầm chỉ trả về một phần dữ liệu. Hãy phân trang bằng cách tăng startRow cho đến khi response trả về rỗng. Trong hướng dẫn lấy toàn bộ dữ liệu hiệu suất, Google khuyến nghị chạy một query cho từng ngày dữ liệu. Cách này giúp bạn nằm trong quota và có một đơn vị dữ liệu rõ ràng để thử lại khi lỗi.
import time, random
from googleapiclient.errors import HttpError
PAGE = 25000
def execute(request, tries=5):
for attempt in range(tries):
try:
return request.execute()
except HttpError as err:
quota = 'quota' in str(err).lower()
if attempt == tries - 1:
raise
if quota:
time.sleep(15 * 60) # short-term load quota: wait 15 minutes
elif err.resp.status in (429, 500, 503):
time.sleep(2 ** attempt + random.random())
else:
raise
def pull_day(site, day, search_type='web',
dims=('date', 'page', 'query', 'device', 'country')):
rows, start = [], 0
while True:
body = {
'startDate': day, 'endDate': day,
'dimensions': list(dims), 'type': search_type,
'rowLimit': PAGE, 'startRow': start,
}
resp = execute(gsc.searchanalytics().query(siteUrl=site, body=body))
batch = resp.get('rows', [])
if not batch:
return rows
rows.extend(batch)
start += PAGE
Vì sao nên lấy dữ liệu cách hiện tại ba ngày?
Google cho biết dữ liệu thường khả dụng sau hai đến ba ngày, đồng thời ngày trong request được diễn giải theo múi giờ Pacific chứ không phải giờ địa phương của bạn. Một tác vụ chạy ở Hà Nội hoặc Berlin nhưng yêu cầu dữ liệu của hôm qua theo giờ địa phương có thể đang truy vấn một ngày Pacific chưa hoàn tất. Hãy tính ngày mục tiêu theo giờ Pacific rồi lùi lại ba ngày. Nếu cần số liệu mới hơn, truyền dataState: 'all'; khi nhóm theo ngày, metadata của response sẽ có first_incomplete_date, và mọi giá trị sau ngày đó vẫn có thể thay đổi.
Tổng chính xác và dữ liệu chi tiết cần dùng hai query khác nhau
Khi nhóm theo trang hoặc truy vấn, Search Console có thể loại bớt dòng để giữ chi phí tính toán ở mức hợp lý. Vì vậy, tổng của dữ liệu kéo theo trang và truy vấn sẽ không khớp với tổng thực tế. Cách đáng tin cậy là chạy hai query mỗi ngày và lưu riêng chúng.
| Mục đích | Dimension | Đánh đổi |
|---|---|---|
| Tổng chính xác | Không có, hoặc chỉ country và device | Không có chi tiết trang hoặc truy vấn |
| Dữ liệu chi tiết để phân tích | Page, query, cùng country và device nếu cần | Một số dòng có thể bị loại bỏ |
Ngay cả dữ liệu chi tiết cũng có giới hạn: API cung cấp tối đa 50.000 dòng mỗi ngày cho mỗi loại tìm kiếm, được sắp xếp theo clicks. Với site lớn, phần long-tail vượt quá giới hạn này sẽ không xuất hiện trong endpoint; đây là điểm mà tính năng xuất sang BigQuery bên dưới có thể giải quyết.
Quota và giới hạn của Search Console API
Các con số dưới đây lấy từ trang giới hạn sử dụng Search Console API của Google, được kiểm tra vào . Quota có thể thay đổi, vì vậy hãy xác nhận lại trước khi tính quy mô cho tác vụ.
| Tài nguyên | Phạm vi | Giới hạn |
|---|---|---|
| Search Analytics | Mỗi site | 1.200 query mỗi phút |
| Search Analytics | Mỗi người dùng | 1.200 query mỗi phút |
| Search Analytics | Mỗi project | 40.000 mỗi phút; 30.000.000 mỗi ngày |
| URL Inspection | Mỗi site | 600 mỗi phút; 2.000 mỗi ngày |
| URL Inspection | Mỗi project | 15.000 mỗi phút; 10.000.000 mỗi ngày |
| Tất cả tài nguyên khác | Mỗi người dùng | 20 mỗi giây; 200 mỗi phút |
Các giới hạn theo phút hiếm khi là vấn đề. Search Analytics còn có load quota, được tính trong các khung 10 phút và một ngày; đây mới là nguyên nhân khiến các pipeline thực tế bị chặn. Tải tăng theo khoảng thời gian truy vấn, đồng thời việc nhóm hoặc lọc theo page hay query string tốn nhiều tài nguyên; nhóm theo cả hai là trường hợp tốn kém nhất. Thông báo lỗi giống nhau cho mọi loại sự kiện quota, vì vậy hãy chẩn đoán dựa trên hành vi: nếu một query duy nhất trong khoảng 10 phút yên ắng vẫn thất bại, bạn đã vượt daily load quota.
- Truy vấn từng ngày một thay vì truy vấn một khoảng thời gian dài.
- Không truy vấn lại dữ liệu đã lưu. Hãy giữ lại các dòng dữ liệu thô.
- Nếu chạm short-term quota, hãy chờ 15 phút; nếu vẫn tiếp diễn, bỏ nhóm page và query hoặc thu hẹp khoảng thời gian.
Tự động hóa URL Inspection và gửi sitemap
Endpoint URL Inspection trả về cùng trạng thái lập chỉ mục mà bạn thấy trên giao diện web: URL có trên Google hay không, Google đã chọn canonical nào và lần crawl gần nhất. Endpoint này chỉ báo cáo trạng thái, không yêu cầu Google lập chỉ mục.
def inspect(site, url):
body = {'inspectionUrl': url, 'siteUrl': site}
res = execute(gsc.urlInspection().index().inspect(body=body))
s = res['inspectionResult']['indexStatusResult']
return {
'url': url,
'state': s.get('coverageState'),
'last_crawl': s.get('lastCrawlTime'),
'google_canonical': s.get('googleCanonical'),
'user_canonical': s.get('userCanonical'),
}
Với giới hạn 2.000 lần kiểm tra mỗi ngày cho mỗi site, bạn không thể kiểm tra hằng ngày một catalog 50.000 URL. Hãy dành quota cho những URL mà thay đổi có ý nghĩa: URL được xuất bản trong tuần qua, các trang có nhiều clicks nhất và những trang vừa bị sụt clicks. Phân bổ các URL còn lại để kiểm tra luân phiên trong tháng. Lưu mọi kết quả để có thể cảnh báo khi coverageState thay đổi hoặc xảy ra canonical mismatch; thông tin này hữu ích hơn nhiều so với một ảnh chụp trạng thái đơn lẻ. Quota được áp dụng theo property, vì vậy chia một site lớn thành các property dạng URL-prefix cho những khu vực chính là cách hợp lệ để mở rộng ngân sách.
Gửi sitemap cần scope đọc/ghi và một lần gọi: gsc.sitemaps().submit(siteUrl=site, feedpath=sitemap_url). Lệnh này chỉ cho Google biết file nằm ở đâu; gửi lại một file không thay đổi sau mỗi lần deploy không đem lại lợi ích gì. Điều thực sự giúp crawl được cải thiện là giá trị lastmod chính xác trong chính sitemap.
Nếu không muốn tự duy trì phần hạ tầng này, các đội ngũ có thể bàn giao cho đơn vị chuyên môn: Netalith triển khai các hệ thống báo cáo và giám sát dạng này trong khuôn khổ dịch vụ tự động hóa SEO.
Khi API chưa đủ: xuất hàng loạt sang BigQuery
Nếu giới hạn 50.000 dòng mỗi ngày hoặc các dòng bị loại khi nhóm theo page và query gây ảnh hưởng đến phân tích, hãy ngừng cố vượt qua giới hạn của API. Search Console có thể lên lịch xuất dữ liệu hiệu suất hằng ngày sang BigQuery. Tính năng này bao gồm toàn bộ dữ liệu hiệu suất có sẵn cho property, ngoại trừ các truy vấn ẩn danh. Dữ liệu xuất hiện chủ yếu trong hai bảng searchdata_site_impression và searchdata_url_impression.
| Nhu cầu | Lựa chọn phù hợp hơn |
|---|---|
| Site nhỏ hoặc vừa, dashboard, cảnh báo | Kéo dữ liệu qua API vào database riêng |
| Các truy vấn long-tail vượt quá 50.000 dòng mỗi ngày | Xuất hàng loạt sang BigQuery |
| Kết hợp Search Console với dữ liệu doanh thu hoặc log | Xuất hàng loạt sang BigQuery |
| Trạng thái lập chỉ mục URL và sitemap | API, vì dữ liệu xuất không bao gồm hai nhóm này |
Một lưu ý thực tế: quá trình xuất bắt đầu từ ngày bạn cấu hình, lịch sử trước ngày đó sẽ không được backfill. Hãy bật tính năng này sớm và tiếp tục chạy API pull cho giai đoạn trước đó. Hai phương án bổ trợ cho nhau chứ không loại trừ nhau.
Indexing API có thể yêu cầu lập chỉ mục các trang thông thường không?
Không. Google mô tả Indexing API là cách thông báo khi trang tuyển dụng hoặc trang video livestream được thêm vào hay gỡ bỏ. API chỉ hoạt động với các trang có structured data JobPosting hoặc BroadcastEvent được nhúng trong VideoObject. API có quota mặc định 200 cho giai đoạn bắt đầu và thử nghiệm, cần được phê duyệt nếu muốn tăng thêm; Google cũng cảnh báo rằng việc lạm dụng, bao gồm dùng nhiều tài khoản để vượt quota, có thể khiến quyền truy cập bị thu hồi.
Những hướng dẫn dùng API này để đẩy bài blog hoặc trang sản phẩm có thể đang hoạt động chỉ là tình cờ, không phải theo thiết kế được hỗ trợ. Xây dựng quy trình production dựa trên hành vi không được hỗ trợ là rủi ro mà bạn phải tự chịu. Với các trang thông thường, những cách được hỗ trợ là sitemap sạch với giá trị lastmod trung thực, liên kết nội bộ mạnh từ các trang đã được crawl và dữ liệu inspection ở trên để tìm những URL bị mắc kẹt.
Lên lịch pipeline và cảnh báo khi traffic sụt giảm
Một tác vụ hằng ngày cần có bốn đặc điểm: nhắm đến ngày cách hiện tại ba ngày theo giờ Pacific, có tính idempotent để chạy lại không tạo dòng trùng, lưu dữ liệu thô và chỉ cảnh báo khi mức thay đổi đủ lớn để đáng quan tâm. Search Console lưu dữ liệu trong khoảng 16 tháng, vì vậy kho dữ liệu riêng cũng là cách duy nhất để so sánh giữa các năm.
Lưu các dòng với khóa duy nhất trên (date, page, query, device, country) và thực hiện upsert. Sau đó, một query có thể so sánh bảy ngày gần nhất với bảy ngày liền trước để đánh dấu những trang thực sự mất traffic.
WITH w AS (
SELECT page,
SUM(CASE WHEN date >= date('now', '-10 day') THEN clicks ELSE 0 END) AS last7,
SUM(CASE WHEN date < date('now', '-10 day') THEN clicks ELSE 0 END) AS prev7
FROM gsc
WHERE date >= date('now', '-17 day')
GROUP BY page
)
SELECT page, prev7, last7
FROM w
WHERE prev7 >= 50 AND last7 < prev7 * 0.7
ORDER BY prev7 - last7 DESC;
Hai ngưỡng trên là lựa chọn mang tính phán đoán, không phải con số do Google quy định. Mức tối thiểu 50 clicks giúp các trang nhỏ không liên tục gửi cảnh báo vì nhiễu, còn mức giảm 30% giúp phát hiện tổn thất thực tế mà không kích hoạt do dao động bình thường theo tuần. Hãy điều chỉnh cả hai dựa trên dữ liệu lịch sử của chính bạn trong một tháng trước khi gửi cảnh báo đến kênh mà mọi người thực sự theo dõi. Bạn có thể chạy tác vụ bằng cron, CI scheduler hoặc container job; lịch chạy quan trọng không bằng việc bảo đảm bước lưu dữ liệu có thể chạy lặp lại an toàn.
Nếu muốn triển khai pipeline này cho các property của mình mà không phải tự xây dựng và duy trì, hãy yêu cầu báo giá miễn phí và mô tả những báo cáo bạn cần.
CÂU HỎI THƯỜNG GẶP
Câu hỏi thường gặp
Search Console API có thể trả về bao nhiêu dòng dữ liệu?
Mỗi request trả về tối đa 25.000 dòng và bạn có thể phân trang bằng startRow. Ngoài ra, API chỉ cung cấp tối đa 50.000 dòng dữ liệu mỗi ngày cho mỗi loại tìm kiếm, được sắp xếp theo clicks. Với phần dữ liệu vượt quá giới hạn này, hãy dùng tính năng xuất hàng loạt sang BigQuery.
Có thể dùng service account với Search Console API không?
Có. Hãy tạo service account, bật Search Console API trong cloud project của service account, sau đó thêm email của service account làm người dùng trên từng property trong Search Console. Nếu bỏ qua bước cấp quyền theo từng property, request có thể trả về danh sách rỗng hoặc lỗi 403 dù việc xác thực đã thành công.
Nên kéo dữ liệu Search Console với tần suất bao lâu?
Mỗi ngày một lần, cho dữ liệu của một ngày. Google khuyến nghị cách này vì giúp nằm trong quota; dữ liệu thường khả dụng sau hai đến ba ngày, nên hãy nhắm đến ngày cách hiện tại khoảng ba ngày theo giờ Pacific.
Search Console API có thể yêu cầu lập chỉ mục một URL không?
Không. Endpoint URL Inspection chỉ báo cáo trạng thái lập chỉ mục. Indexing API có thể thông báo cho Google về một số trang, nhưng Google chỉ ghi nhận API này cho trang tuyển dụng và trang video livestream; đây không phải cách được hỗ trợ để đẩy các trang thông thường.
Nên dùng API hay tính năng xuất hàng loạt sang BigQuery?
Hãy dùng API cho URL inspection, sitemap và các tác vụ kéo dữ liệu hằng ngày quy mô nhỏ vào database riêng. Dùng tính năng xuất sang BigQuery khi cần dữ liệu long-tail vượt quá 50.000 dòng mỗi ngày hoặc muốn kết hợp Search Console với dữ liệu khác. Dữ liệu xuất không được backfill, nên hãy bật tính năng này sớm.