最近遇到一個需求需要將上千條的數據寫入到基於Wordpress搭建的系統中,但是對於底層數據錄的寫入邏輯不是很清楚,通過sql各種寫入也沒有完全達到效果。
後面想了想或許可以換一個方向,不能從底層邏輯寫入數據那就通過正常操作寫入。由於數據量大所以需要自動化處理,這時候就想到了之前用過的Puppeteer,這個庫可以模擬操作瀏覽器的各種行為,包括獲取數據和操作提交等。對於這個場景很適合,不用管底層的實現邏輯,也不需要去扒源碼瞭解各種加密加簽的邏輯,只需要模擬操作提交數據即可。
複雜的問題瞬間簡單了,在這篇文章中記錄如何使用Puppeteer批量提交數量。
安裝Puppeteer
在這之前確保你已經安裝了Node.js。運行以下命令安裝Puppeteer:
npm install puppeteer
Puppeteer腳本
接下來編寫需要執行的腳本,創建一個名為puppeteer.js的文件,並添加以下代碼:
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: false
});
const page = await browser.newPage();
await page.goto('https://baidu.com');
await browser.close();
})();
puppeteer.launch() 是用於啓動一個瀏覽器實例,為後續的網頁操作和自動化測試提供基礎。可以接受一些配置選項,如指定瀏覽器的路徑、是否啓用無頭模式、設置視口大小等。完整配置還有很多,可查閲官網瞭解。
保持用户狀態
需要寫入的系統是需要登錄後才能操作且需要多次操作,所以在操作過程中需要記錄用户狀態。這一點我們可以在初始化瀏覽器實例的時候配置 userDataDir,userDataDir 用於指定一個目錄,該目錄用於存儲瀏覽器的用户數據,如緩存、Cookie、本地存儲數據等。可以讓 Puppeteer 在每次啓動瀏覽器時都使用相同的用户數據,從而保持用户狀態的連續性。
const browser = await puppeteer.launch({
userDataDir: 'userA'
});
模擬登錄
然後就是第一次的模擬登錄和後續操作校驗登錄狀態。通過 page.cookies() 獲取存儲的用户數據,如果不存在則模擬登錄。
// 從puppeteer中獲取cookie
const cookies = await page.cookies();
let isLogin = false
cookies.forEach(json => {
if (json.name.includes('wordpress')) {
isLogin = true
}
});
console.log('[ isLogin ] >', isLogin)
if (!isLogin) {
// 模擬輸入用户名密碼
await page.type('#user_login', 'XXXX', { delay: 100 });
await page.type('#user_pass', 'XXXX', { delay: 100 });
// 模擬點擊
await page.click('#rememberme', { delay: 110 });
await page.click('#wp-submit', { delay: 120 });
// 等待頁面完全加載
await page.waitForNavigation()
}
數據處理
接下來就是業務數據處理了,首先將數據轉換成JSON方便批量處理。每次處理一批數組,這裏在for循環中使用 Promise 同步處理,待所有的數據都處理完成後關閉瀏覽器結束腳本。在 performAsyncOperation 中執行具體的數據操作過程。
const list = require('./list.js')
function performAsyncOperation(item) {
return new Promise(async (resolve, reject) => {
// todo item
resolve();
});
}
// 使用async函數來包裹異步操作
async function processItems() {
for (const item of list) {
// 使用await等待異步操作完成
await performAsyncOperation(item);
}
console.log('All items processed');
await browser.close();
}
processItems()
這裏有一點特殊處理,要寫入的數據是在iframe中的元素,需要通過以下方式對iframe中的dom進行修改賦值。
const elementHandle = await page.waitForSelector('#content_ifr');
const frame = await elementHandle.contentFrame();
await frame.waitForSelector('p:nth-child(1)');
const description = item.description
// 在 iframe 中使用 evaluate 方法來修改元素內的 DOM
await frame.evaluate((description) => {
// 在這裏可以編寫 JavaScript 代碼來修改 iframe 內的 DOM
document.querySelector('p:nth-child(1)').textContent = description
}, description);
更新完一條數據後進行下一條數據的寫入,這裏頁面提交數據後界面發生了變化,需要重新回到開始的頁面繼續處理。回到開始的發佈頁面後執行成功回調繼續下一條數據處理,當所有的數據處理完成則結束腳本。
// 點擊發布
await page.click('#publish')
// 等待頁面更新
await page.waitForNavigation()
// 點擊回到發佈頁面
await page.click('.page-title-action', { delay: 300 })
// 成功回調繼續下一條處理
resolve();
總結
Puppeteer是一個強大的庫,它能夠讓開發者以編程方式控制Chrome或Chromium。這使數據獲取或操作頁面數據變得更加容易,特別是對於需要與JavaScript交互的頁面。
通過上面的例子,你應該對如何使用Puppeteer來處理數據有了一個基本的瞭解。Puppeteer的能力遠不止於此,你可以創建更復雜的腳本來模擬用户登錄、填寫表單、獲取簽名數據等。希望這篇文章對你有所幫助~
看完本文如果覺得有用,記得點個贊支持,收藏起來説不定哪天就用上啦~
專注前端開發,分享前端相關技術乾貨,公眾號:南城大前端(ID: nanchengfe)