用Node+wechaty寫一個爬蟲指令碼每天定時給女(男)朋友發微信暖心話
阿新 • • 發佈:2019-06-11
wechatBot
微信每日說,每日自動傳送微信訊息給你心愛的人
專案介紹
靈感來源
在掘金看到了一篇《用Node + EJS寫一個爬蟲指令碼每天定時女朋友發一封暖心郵件》後,
在評論區偶然看到一位讀者說可不可以用微信實現一下。然後最近剛好在做微信機器人的小專案,那就把這個定時任務放到微信上去做吧,說幹就幹,擼了一下午終於擼出來了。
專案地址
github:https://github.com/gengchen528/wechatBot
使用庫
- wechaty - 微信操作
- node-schedule - 定時任務
- superagent - 爬取頁面資訊
- cheerio - 抓取頁面
- qrcode-terminal - 終端顯示二維碼
功能
- 定時給朋友傳送每日天氣提醒以及每日一句
- 根據關鍵詞自動加好友和自動拉群功能
- 後續繼續擴充套件吧...(你有好的想法也可以提pr)
資料來源
- 每日一句和上面的大佬一樣也是來自one
- 天氣資訊來自墨跡天氣
定時任務
node-schedule非你莫屬了,
可以定時每個月、每個禮拜、每天具體什麼時候執行什麼任務
實現效果
由於是微信定時傳送訊息,較郵件來說,微信無法把圖片和文字放在同一訊息框中,所以美觀度來說可能沒有郵件好,不過文字進行排版後還是可以的,由於時間倉促,所以文字比較少,後續會繼續增加內容;
程式碼說明
目錄結構
- config: 存放公共變數和superagent的配置
- schedule: 任務排程的配置
- superagent: 獲取每日一句和天氣資訊
- untils: 抽取的共用方法
核心程式碼
index.js
關於微信的登入,定時任務的建立,傳送資訊的獲取都在這個檔案裡
/** * WechatBot * - https://github.com/gengchen528/wechatBot */ const {Wechaty,Friendship} = require('wechaty') const schedule = require('./schedule/index') const config = require('./config/index') const untils = require('./untils/index') const superagent = require('./superagent/index') const {FileBox} = require('file-box') //檔案讀取模組 // 二維碼生成 function onScan (qrcode, status) { require('qrcode-terminal').generate(qrcode) // 在console端顯示二維碼 const qrcodeImageUrl = [ 'https://api.qrserver.com/v1/create-qr-code/?data=', encodeURIComponent(qrcode), ].join('') console.log(qrcodeImageUrl) } // 登入 async function onLogin (user) { console.log(`貼心小助理${user}登入了`) // 登陸後建立定時任務 schedule.setSchedule(config.SENDDATE,()=>{ console.log('你的貼心小助理開始工作啦!') main() }) } //登出 function onLogout(user) { console.log(`${user} 登出`) } // 監聽對話 根據關鍵詞自動加群 async function onMessage (msg) { const contact = msg.from() // 發訊息人 const content = msg.text() //訊息內容 const room = msg.room() //是否是群訊息 const roomCodeUrl = FileBox.fromUrl(config.ROOMCODEURL) //來自url的檔案 const roomCodeLocal = FileBox.fromFile(config.ROOMLOCALPATH) //新增本地檔案 if (msg.self()) { return } if(room){ // 如果是群訊息 const topic = await room.topic() console.log(`群名: ${topic} 發訊息人: ${contact.name()} 內容: ${content}`) }else { // 如果非群訊息 console.log(`發訊息人: ${contact.name()} 訊息內容: ${content}`) let addRoomReg = eval(config.ADDROOMWORD) let roomReg = eval(config.ROOMNAME) if(addRoomReg.test(content)&&!room){ let keyRoom = await this.Room.find({topic: roomReg}) if(keyRoom){ try{ await contact.say(roomCodeLocal||roomCodeUrl) await keyRoom.say('微信每日說:歡迎新朋友', contact) }catch (e) { console.error(e) } } }else { await contact.say('你好,不要輕易調戲我,我只會發群二維碼,不會聊天的!') await contact.say('請回復暗號:加群 獲取群二維碼圖片') } } } // 自動加好友功能 async function onFriendShip(friendship) { let logMsg try { logMsg = '新增好友' + friendship.contact().name() console.log(logMsg) switch (friendship.type()) { /** * * 1. New Friend Request * * when request is set, we can get verify message from `request.hello`, * and accept this request by `request.accept()` */ case Friendship.Type.Receive: let addFriendReg = eval(config.ADDFRIENDWORD) if (addFriendReg.test(friendship.hello())) { logMsg = '自動新增好友,因為驗證資訊中帶關鍵字‘每日說’' await friendship.accept() } else { logMsg = '沒有通過驗證 ' + friendship.hello() } break /** * * 2. Friend Ship Confirmed * */ case Friendship.Type.Confirm: logMsg = 'friend ship confirmed with ' + friendship.contact().name() break } } catch (e) { logMsg = e.message } console.log(logMsg) } // 自動發訊息功能 async function main() { let contact = await bot.Contact.find({name:config.NICKNAME}) || await bot.Contact.find({alias:config.NAME}) // 獲取你要傳送的聯絡人 let one = await superagent.getOne() //獲取每日一句 let weather = await superagent.getWeather() //獲取天氣資訊 let today = await untils.formatDate(new Date())//獲取今天的日期 let memorialDay = untils.getDay(config.MEMORIAL_DAY)//獲取紀念日天數 let str = today + '<br>' + '今天是我們在一起的第' + memorialDay + '天' + '<br><br>今日天氣早知道<br><br>' + weather.weatherTips +'<br><br>' +weather.todayWeather+ '每日一句:<br><br>'+one+'<br><br>'+'------來自最愛你的我' await contact.say(str)//傳送訊息 } const bot = new Wechaty() bot.on('scan', onScan) bot.on('login', onLogin) bot.on('logout', onLogout) bot.on('message', onMessage) bot.on('friendship', onFriendShip) bot.start() .then(() => console.log('開始登陸微信')) .catch(e => console.error(e))
superagent/index.js
const superagent = require('../config/superagent')
const config = require('../config/index')
const cheerio = require('cheerio')
async function getOne() { // 獲取每日一句
let res = await superagent.req(config.ONE,'GET')
let $ = cheerio.load(res.text)
let todayOneList = $('#carousel-one .carousel-inner .item')
let todayOne = $(todayOneList[0]).find('.fp-one-cita').text().replace(/(^\s*)|(\s*$)/g, "")
return todayOne;
}
async function getWeather() { //獲取墨跡天氣
let url = config.MOJI_HOST+config.CITY+'/'+config.LOCATION
let res = await superagent.req(url,'GET')
let $ = cheerio.load(res.text)
let weatherTips = $('.wea_tips em').text()
const today = $('.forecast .days').first().find('li');
let todayInfo = {
Day:$(today[0]).text().replace(/(^\s*)|(\s*$)/g, ""),
WeatherText:$(today[1]).text().replace(/(^\s*)|(\s*$)/g, ""),
Temp:$(today[2]).text().replace(/(^\s*)|(\s*$)/g, ""),
Wind:$(today[3]).find('em').text().replace(/(^\s*)|(\s*$)/g, ""),
WindLevel:$(today[3]).find('b').text().replace(/(^\s*)|(\s*$)/g, ""),
PollutionLevel:$(today[4]).find('strong').text().replace(/(^\s*)|(\s*$)/g, "")
}
let obj = {
weatherTips:weatherTips,
todayWeather:todayInfo.Day + ':' + todayInfo.WeatherText + '<br>' + '溫度:' + todayInfo.Temp + '<br>'
+ todayInfo.Wind + todayInfo.WindLevel + '<br>' + '空氣:' + todayInfo.PollutionLevel + '<br>'
}
return obj
}
module.exports ={
getOne,getWeather
}
專案執行
由於需要安裝chromium, 所以要先配置一下映象,注意由於wechaty的限制,最好使用node10以上版本
npm
npm config set registry https://registry.npm.taobao.org
npm config set disturl https://npm.taobao.org/dist
npm config set puppeteer_download_host https://npm.taobao.org/mirrors
yarn
yarn config set registry https://registry.npm.taobao.org
yarn config set disturl https://npm.taobao.org/dist
yarn config set puppeteer_download_host https://npm.taobao.org/mirrors
然後進行專案安裝
git clone [email protected]:gengchen528/wechatBot.git
cd wechatBot
npm install 或 cnpm install
引數配置
wechatBot/config/index.js
// 配置檔案
module.exports ={
// 基礎定時傳送功能配置項(必填項)
NAME:'A兔子',//備註姓名
NICKNAME:'嗯哼', //暱稱
MEMORIAL_DAY:'2015/04/18', //你和收信者的紀念日
CITY:'shanghai',//收信者所在城市
LOCATION:'pudong-new-district',//收信者所在區 (可以訪問墨跡天氣網站後,查詢區的英文拼寫)
SENDDATE:'0 0 8 * * *',//定時傳送時間 每天8點0分0秒傳送,規則見 /schedule/index.js
ONE:'http://wufazhuce.com/',////ONE的web版網站
MOJI_HOST:'https://tianqi.moji.com/weather/china/', //中國墨跡天氣url
//高階功能配置項(非必填項)
AUTOADDFRIEND:false,//自動加好友功能 預設關閉
AUTOADDROOM:false,//自動拉群功能 預設關閉
AUTOREPLY:false,//自動聊天功能 預設關閉
AIBOTAPI:'http://www.tuling123.com/openapi/api',//圖靈機器人API 註冊地址http://www.turingapi.com/
APIKEY:'你的圖靈機器人apikey',//圖靈機器人apikey
ROOMNAME:'/^你的群名/i', //群名(請只修改中文,不要刪除符號,這是正則)
ADDFRIENDWORD:'/你要觸發的關鍵詞/i',//自動加好友觸發的關鍵詞(請只修改中文,不要刪除符號,這是正則)
ADDROOMWORD:'/加群/',//自動傳送群圖片觸發關鍵詞(請只修改中文,不要刪除符號,這是正則)
ROOMCODEURL:'http://image.bloggeng.com/qun.png',//群二維碼url連結(與本地群二維碼路徑選填一個)
ROOMLOCALPATH:'./static/qun.png',//本地群二維碼圖片路徑(與群url選填一個)
}
開始執行
npm run start
然後掏出你的手機,最好使用小號,掃描控制檯的二維碼即可
待解決問題
- 由於微信登入和郵件登入不同,所以無法使用程序守護工具,目前沒有測試是否能夠長時間登入(目前已經解決,第一次需要使用node啟動,生成狀態維持檔案,生成後即可使用pm2等程序守護工具)
- 因為node的原因,如果發生錯誤,可能會導致任務無法進行,需要手動重啟並登入(已解決)
- 最好能夠使用小號登入,如果是常用微信登入,在電腦客戶端登陸後可能會wechaty擠掉
- 墨跡天氣頁面在獲取的時候可能會存在延時,有時可能獲取不到
後續功能
- 為了防止佔用你的微訊號,你和你的愛人新增我的微信後。你傳送指定內容,我將會每天幫你傳送訊息(已實現)
- 添加了圖靈機器人聊天功能(已實現)
- 日常定時小提醒功能 (已實現https://github.com/gengchen528/wechat-assistant)
- 還有在思考中...(你有好的想法也可以提出來)
最後
因為給這個微信加了自動加好友和拉群功能,所以有興趣的小夥伴可以加我的微信進行測試,記得在加好友的時候帶上暗號:微信每日說
,加好友後傳送加群
,會自動傳送群的二維碼;
注意 加好友請在驗證中填寫 微信每日說
才可以自動加好友
趕快親自試一試吧,相信你會挖掘出更多好玩的功能
github:https://github.com/gengchen528/wechatBot
另外我的公眾號已經接入微軟小冰,關注後發語音會有小姐姐的聲音陪你聊天,也可以和她文字聊天,有興趣可以試試看,單身的歡迎來撩