node+puppeteer定時發送微博

實現功能:登陸微博自動轉發特定用戶的下的第一條微博

實現步驟:

1. 初始化項目

你須要安裝版本 8 以上的 Node,你能夠在這裏找到安裝方法。確保選擇Current版本,由於它是 8+。 安裝完node後新建一個項目文件夾node

mkdir Project
cd Project
複製代碼

初始化一個node項目,在交互式命令中輸入依次項目名、版本號、描述...等信息。直接enter鍵保持默認選項便可git

MacdeMacBook-Pro:Project mac$ npm init
...
package name: (project) test
version: (1.0.0) 
description: 
entry point: (index.js) 
test command: 
git repository: 
keywords: 
author: 
license: (ISC) 
About to write to /Users/mac/Project/package.json:

{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}


Is this OK? (yes) 
複製代碼

這是會生成一個以下目錄結構的文件夾github

Project
        - index.js  // 入口文件
        - package.json
複製代碼

2. 安裝依賴

puppeteer

Puppeteer(中文翻譯」木偶」) Google Chrome 團隊官方的無界面(Headless)Chrome 工具。也能夠經過配置使用完整的(非無頭)Chrome. 使用 Puppeteer,至關於同時具備 Linux 和 Chrome 雙端的操做能力,在瀏覽器中手動完成的大部分事情均可以使用 Puppeteer 完成,應用場景可謂很是之多。如:npm

  • 從網站抓取你須要的內容。
  • 模擬人爲操做自動錶單提交,UI測試,鍵盤輸入等。
  • 建立一個最新的自動化測試環境。使用最新的JavaScript和瀏覽器功能,直接在最新版本的Chrome中運行測試。
  • 捕獲您的網站的時間線跟蹤,以幫助診斷性能問題。
安裝

npm i puppeteer -S -Djson

用法

puppeteer的具體用法能夠參考puppeteer中文文檔api

node-schedule

Node Schedule是用於Node.js下的靈活的cron式和非cron式任務調度程序。 它容許您使用可選的重複規則來安排任務(任意函數)在特定日期執行。數組

安裝:

npm i node-schedule -S -D瀏覽器

用法:
  1. Cron風格定時器
const schedule = require('node-schedule');

const  scheduleCronstyle = ()=>{
  //每分鐘的第30秒定時執行一次:
    schedule.scheduleJob('30 * * * * *',()=>{
        console.log('scheduleCronstyle:' + new Date());
    }); 
}

scheduleCronstyle();
複製代碼

schedule.scheduleJob的回調函數中寫入要執行的任務代碼,一個定時器就完成了!bash

規則參數講解 *表明通配符less

*  *  *  *  *  *
┬ ┬ ┬ ┬ ┬ ┬
│ │ │ │ │  |
│ │ │ │ │ └ day of week (0 - 7) (0 or 7 is Sun)
│ │ │ │ └───── month (1 - 12)
│ │ │ └────────── day of month (1 - 31)
│ │ └─────────────── hour (0 - 23)
│ └──────────────────── minute (0 - 59)
└───────────────────────── second (0 - 59, OPTIONAL)
複製代碼

6個佔位符從左到右分別表明:秒、分、時、日、月、周幾

表示通配符,匹配任意,當秒是時,表示任意秒數都觸發,其它類推

關於cron表達式具體用法能夠參考cron表達式工具

  1. 對象文本語法定時器
const schedule = require('node-schedule');

function scheduleObjectLiteralSyntax(){

    // 每週一的下午16:11分觸發,其它組合能夠根據我代碼中的註釋參數名自由組合
    schedule.scheduleJob({hour: 16, minute: 11, dayOfWeek: 1}, function(){
        console.log('scheduleObjectLiteralSyntax:' + new Date());
    });
}
scheduleObjectLiteralSyntax();
複製代碼
  1. 遞歸規則調度定時器

您能夠構建重複規則以指定什麼時候應重複做業。 例如,考慮如下規則,該規則在每小時的42分鐘以後每小時執行一次函數:

var schedule = require('node-schedule');
 
var rule = new schedule.RecurrenceRule();
rule.minute = 42;
 
var j = schedule.scheduleJob(rule, function(){
  console.log('The answer to life, the universe, and everything!');
});
複製代碼

您還可使用數組來指定可接受值的列表,並使用Range對象來指定起始值和結束值的範圍,以及可選的step參數。 例如,這將在週四,週五,週六和週日下午5點打印一條消息:

var rule = new schedule.RecurrenceRule();
rule.dayOfWeek = [0, new schedule.Range(4, 6)];
rule.hour = 17;
rule.minute = 0;
 
var j = schedule.scheduleJob(rule, function(){
  console.log('Today is recognized by Rebecca Black!');
});
複製代碼

RecurrenceRule屬性

  • second (0-59)
  • minute (0-59)
  • hour (0-23)
  • date (1-31)
  • month (0-11)
  • year
  • dayOfWeek (0-6) Starting with Sunday

3. 代碼編寫

登陸功能:

const browser = await puppeteer.launch({
    headless: false,
    slowMo: 250,
    executablePath: ''
});  // 建立一個 Browser 實例
const page = (await browser.pages())[0];
await page.setViewport({
    width: 1280,
    height: 800
});  // 設置視口

await page.goto("https://weibo.com/"); // 跳轉目標頁面
await page.waitForNavigation();   //等待頁面加載完成
await page.type("#loginname", username); // 輸入用戶名
await page.type("#pl_login_form > div > div:nth-child(3) > div.info_list.password > div > input", password);   // 輸入密碼
await page.click("#pl_login_form > div > div:nth-child(3) > div:nth-child(6)");  // 點擊登陸
await page.waitForNavigation();   //等待跳轉的頁面加載完成
複製代碼

登陸之後轉發操做:

await page.type(".gn_search_v2>input", searchText);  // 等待新窗口加載後 搜索框輸入須要搜索的用戶
await page.click(".gn_search_v2>a");  // 點擊搜索
await page.waitFor(3000);
await page.click('.m-con-l> div > div.card-wrap:nth-child(1) .avator');  // 點擊搜索後出現的用戶頭像
await page.waitFor(10000); // 等待5s 新窗口打開搜索後的用戶主頁頁面
const page2 = ( await browser.pages() )[1]; //獲得全部窗口使用列表索引獲得新的窗口
await page2.setViewport({
    width: 1280,
    height: 800
});
await page2.waitFor('.WB_feed.WB_feed_v3.WB_feed_v4'); // 等待加載元素
const result = await page2.evaluate(() => {
    let text = document.querySelector("#Pl_Official_MyProfileFeed__23 > div > div:nth-child(2) > div.WB_feed_detail.clearfix > div.WB_detail > div.WB_text.W_f14").innerText;
    return {
        text,
    };
});
await page2.click('#Pl_Official_MyProfileFeed__23 > div > div:nth-child(2) > div.WB_feed_handle > div > ul > li:nth-child(2) > a > span > span')
await page2.waitFor('.p_input.p_textarea');
await page2.type('.p_input.p_textarea', result.text)
await page2.click('div.content > div.layer_forward > div > div:nth-child(2) > div > div.WB_feed_repeat.forward_rpt1 > div > div.WB_feed_publish.clearfix > div > div.p_opt.clearfix > div.btn.W_fr > a');
await page.waitFor(1000);
await browser.close();//關閉打開的瀏覽器
複製代碼

任務定時觸發

這裏使用的的是基於遞歸規則調度定時器

let rule = null;
rule = new schedule.RecurrenceRule();
rule.dayOfWeek = [new schedule.Range(1, 6)];
rule.hour = 12;
rule.minute = 0; // 定義一個每週1到週六中午12點的規則
try {
    login(config.username, config.password);
} catch (error) {
    console.log(error);
}

j = schedule.scheduleJob(rule, async () => { // 定時任務
    try {
        login(config.username, config.password);
    } catch (error) {
        console.log(error);
    }
});
複製代碼

觸發任務

node index.js

源碼地址:github地址

相關文章
相關標籤/搜索