Crawl Dữ Liệu Web Về Google Sheets Tự Động Với Apps Script
14 tháng 5, 2026
5 phút đọc
Apps Script Có Thể Crawl Web Không?
Có — Apps Script cung cấp UrlFetchApp để gọi HTTP request. Bạn có thể lấy dữ liệu từ website, REST API, RSS/XML feed và lưu vào Google Sheets. Phù hợp cho: theo dõi giá sản phẩm, lấy tỷ giá ngân hàng, đọc RSS tin tức, gọi API thời tiết.
Crawl Từ REST API Công Khai
/**
* Lấy tỷ giá USD/VND từ API và ghi vào Sheet
*/
function fetchExchangeRate() {
try {
const url = 'https://api.exchangerate-api.com/v4/latest/USD';
const response = UrlFetchApp.fetch(url, { muteHttpExceptions: true });
if (response.getResponseCode() !== 200) {
throw new Error('API error: HTTP ' + response.getResponseCode());
}
const data = JSON.parse(response.getContentText());
const vndRate = data.rates.VND;
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Tỷ Giá')
|| SpreadsheetApp.getActiveSpreadsheet().insertSheet('Tỷ Giá');
sheet.appendRow([new Date(), 'USD/VND', vndRate, data.date]);
console.log('Exchange rate saved: 1 USD = ' + vndRate + ' VND');
} catch (err) {
console.error('fetchExchangeRate error: ' + err.toString());
throw err;
}
}
Parse HTML Với XmlService
/**
* Crawl giá sản phẩm từ trang web (ví dụ: lấy giá từ thẻ có class cụ thể)
* Lưu ý: Chỉ dùng trên website cho phép scraping theo robots.txt
*/
function crawlProductPrice(productUrl) {
try {
const response = UrlFetchApp.fetch(productUrl, {
muteHttpExceptions: true,
followRedirects: true
});
if (response.getResponseCode() !== 200) throw new Error('HTTP ' + response.getResponseCode());
const html = response.getContentText();
// Dùng regex để extract giá (thay pattern theo cấu trúc HTML thực tế)
const priceMatch = html.match(/class="product-price"[^>]*>([^<]+)/);
const nameMatch = html.match(/<title>([^<]+)</title>/);
const price = priceMatch ? priceMatch[1].replace(/[^d]/g, '') : 'N/A';
const name = nameMatch ? nameMatch[1].trim() : productUrl;
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Giá Sản Phẩm')
|| SpreadsheetApp.getActiveSpreadsheet().insertSheet('Giá Sản Phẩm');
if (sheet.getLastRow() === 0) {
sheet.appendRow(['Thời gian', 'Tên sản phẩm', 'Giá (VND)', 'URL']);
}
sheet.appendRow([new Date(), name, price, productUrl]);
console.log('Price crawled: ' + name + ' = ' + price);
return { name, price };
} catch (err) {
console.error('crawlProductPrice error: ' + err.toString());
return { name: productUrl, price: 'ERROR' };
}
}
Crawl RSS Feed Tin Tức
function fetchRSSFeed(feedUrl, sheetName) {
try {
const response = UrlFetchApp.fetch(feedUrl, { muteHttpExceptions: true });
if (response.getResponseCode() !== 200) throw new Error('HTTP ' + response.getResponseCode());
const xml = XmlService.parse(response.getContentText());
const root = xml.getRootElement();
const ns = root.getNamespace();
const items = root.getChild('channel', ns)
? root.getChild('channel', ns).getChildren('item', ns)
: root.getChildren('entry', ns); // Atom feed
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName(sheetName) || ss.insertSheet(sheetName);
if (sheet.getLastRow() === 0) sheet.appendRow(['Ngày', 'Tiêu đề', 'Link', 'Mô tả']);
let added = 0;
items.forEach(item => {
const title = item.getChildText('title', ns) || '';
const link = item.getChildText('link', ns) || '';
const pubDate = item.getChildText('pubDate', ns) || item.getChildText('published', ns) || '';
const desc = (item.getChildText('description', ns) || '').replace(/<[^>]+>/g, '').substring(0, 200);
sheet.appendRow([pubDate ? new Date(pubDate) : new Date(), title, link, desc]);
added++;
});
console.log('RSS: added ' + added + ' items from ' + feedUrl);
} catch (err) {
console.error('fetchRSSFeed error: ' + err.toString());
throw err;
}
}
Xử Lý Rate Limit Và Retry
function fetchWithRetry(url, options, maxRetries) {
maxRetries = maxRetries || 3;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const resp = UrlFetchApp.fetch(url, { ...options, muteHttpExceptions: true });
if (resp.getResponseCode() === 429) {
Utilities.sleep(attempt * 2000); // Back-off: 2s, 4s, 6s
continue;
}
return resp;
} catch (err) {
if (attempt === maxRetries) throw err;
Utilities.sleep(1000);
}
}
}
Lưu Ý Pháp Lý
- Kiểm tra
robots.txtcủa website trước khi crawl. - Không crawl dữ liệu cá nhân hay có bản quyền mà không được phép.
- Ưu tiên dùng API chính thức nếu website có cung cấp.
- Thêm
Utilities.sleep()giữa các request để tránh bị block IP.
Chia sẻ bài viết:
Tuân Hoang
Đội ngũ SheetStore
Google SheetsGoogle Apps ScriptCRMAutomationPhần mềm quản lý doanh nghiệp
Google Workspace Certified, 5+ years experience
Bạn thấy bài viết hữu ích?
Đăng ký nhận thông báo khi có bài viết mới.