線報屋-賺客吧

 找回密碼
 立即注冊
自助購買限時2元/天
自助購買限時2元/天
自助購買限時2元/天
自助購買限時2元/天
自助購買限時2元/天
自助購買限時2元/天
自助購買限時2元/天
自助購買限時2元/天
自助購買限時2元/天
自助購買限時2元/天
自助購買限時2元/天
自助購買限時2元/天
查看: 2797|回復: 0
打印 上一主題 下一主題

從零編寫一只會賺錢的爬蟲

[復制鏈接]
跳轉到指定樓層
樓主
發表于 2020-7-4 10:17 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式

79淘薅羊毛論壇網站限時開放注冊!加入79淘,交流、分享一手實時活動線報!

您需要 登錄 才可以下載或查看,沒有帳號?立即注冊

x

[backcolor=rgba(255, 255, 255, 0.5)]本文介紹的是如何編寫一只會賺錢的爬蟲,那如何編寫一只爬蟲來賺錢呢?且聽我一一道來,在開始之前我們不得不提到一個名次“羊毛黨”,現今社會網絡異常發達,各種各樣的平臺為了搶用戶,拉新,推廣或者一些其他的目的都紛紛推出了一些有獎活動,比如注冊送紅包,玩游戲領紅包,邀請送紅包啦之類的,這個時候就出現了一批人,他們會從不同渠道獲得這些信息,然后專門薅這些羊毛,隨便每筆今個可能不多,但是積少成多,參加的活動多了也是一筆很客觀的收入。

[backcolor=rgba(255, 255, 255, 0.5)]上面我們提到了渠道,有些人可能有關系能得到內部消息,但是大部分人都是沒有這種關系的,所以只能靠那些有內幕消息的羊毛大佬分享的信息來薅羊毛,但是別人為什么把信息分享給你呢?因為邀請拉人頭有獎勵呀,這個時候網絡上又誕生了一大批羊毛資訊網站,QQ群,微信群,而我們本節的目的主要就是編寫一只從各個羊毛資訊網站抓取信息,定時抓取,然后生成簡報發送給我們的爬蟲。

[backcolor=rgba(255, 255, 255, 0.5)]在開始之前首先需要確保我們開發的機器已經正確安裝了nodejs,如果尚未安裝,可以參考后面的網站進行安裝,http://www.runoob.com/nodejs/nodejs-install-setup.html,下面我們就正式開始會賺錢爬蟲的開發了,你準備好了嗎?

[backcolor=rgba(255, 255, 255, 0.5)]一、首先我們新建文件夾moneyRobot用于存儲我們的項目文件,并新建文件readed.json文件用于存儲抓取過的鏈接,之后打開控制臺進入該目錄(windows電腦可以在按住shift鍵的同時在該目錄中右擊選擇從此處打開命令行),然后運行命令:

[backcolor=rgba(255, 255, 255, 0.5)][backcolor=white !important][size=1em]
[size=1em]1

[size=1em][size=1em]npm init -y



[backcolor=rgba(255, 255, 255, 0.5)]這一步的主要目的是初始化項目生成package.json文件記錄我們的后面所需要的一些項目依賴。接著我們就開始安裝我們的項目依賴了

[backcolor=rgba(255, 255, 255, 0.5)][backcolor=white !important][size=1em]
[size=1em]1

[size=1em][size=1em]npm install request cheerio fs-extra iconv-lite --save



[backcolor=rgba(255, 255, 255, 0.5)]通過上面的命令我們就安裝好了這個項目所有的依賴了,接下來準備開始進入項目的開發了,在動手編寫之前我們先構思一下,首先這樣的網站并不只有一個,我們也不會只抓取一個,而是要抓取很多個然后綜合得到的信息,但是對于每個網站我們不可能都寫一份代碼呀,所以我們要想一個辦法讓我們的代碼對大部分網站都適用,其實寫過爬蟲的應該都知道其實對于這種靜態網站其實抓取都差不多,只不過是節點不一樣罷了,當然要除開異步獲取內容的,所以也又很多辦法讓它和那些直接輸出內容的靜態網站一樣抓取,這里不多做討論,為了讓我們能用一份代碼抓取不同的網站,我構造了以下數據結構:

[backcolor=rgba(255, 255, 255, 0.5)][backcolor=white !important][size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em][size=1em][{
[size=1em]  url: '',
[size=1em]  selector: '',
[size=1em]  isGBK: false
[size=1em]}]



[backcolor=rgba(255, 255, 255, 0.5)]url字段表示待抓取的網址,selector表示的是抓取節點的選擇器,isGBK表示這個網站是不是GB2312或者GBK編碼,這種編碼響應信息需要用iconv-lite這個庫來做轉換,然后我們開始編寫單個URL的抓取方法:

[backcolor=rgba(255, 255, 255, 0.5)][backcolor=white !important][size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em]29

[size=1em]30

[size=1em]31

[size=1em]32

[size=1em]33

[size=1em]34

[size=1em]35

[size=1em]36

[size=1em]37

[size=1em]38

[size=1em][size=1em]function grab(item) {
[size=1em]  const { url, selector, headers = {} } = item;
[size=1em]  const oldData = fs.readJsonSync(READED_PATH);
[size=1em]  const grabUrl = url;
[size=1em]  request({
[size=1em]    url,
[size=1em]    encoding: null,
[size=1em]    headers: Object.assign({}, headers, {
[size=1em]      userAgent: 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
[size=1em]    })
[size=1em]  }, (err, response, body) => {
[size=1em]    if (err) {
[size=1em]      startList();
[size=1em]    } else {
[size=1em]      const newBody = item.isGBK ? iconv.decode(body,'gb2312').toString() : body.toString();
[size=1em]      const $ = cheerio.load(newBody);
[size=1em]      const list = $(selector);
[size=1em]      list.each(function() {
[size=1em]        const _this = $(this);
[size=1em]        let url = _this.attr('href');
[size=1em]        if (!/^https?/.test(url)) {
[size=1em]          url = joinPath(grabUrl, url);
[size=1em]        }
[size=1em]        const title = _this.text().replace(/\d{2}:?\d{2}:?\d{2}/g, '');
[size=1em]        const isRead = checkIsRead(oldData, url);
[size=1em]        if (!isRead && title.trim() && !RegExp(FILTER_WORDS.join('|')).test(title)) {
[size=1em]          oldData.unshift(url);
[size=1em]          newData.push({
[size=1em]            title,
[size=1em]            url
[size=1em]          });
[size=1em]        }
[size=1em]      });
[size=1em]      fs.writeJsonSync(READED_PATH, oldData);
[size=1em]      startList();
[size=1em]    }
[size=1em]  });
[size=1em]}



[backcolor=rgba(255, 255, 255, 0.5)]其中READED_PATH表示的是記錄已經抓取過的鏈接記錄的本地文件地址,文件以JSON方式記錄,startList方法是遍歷所有待抓取地址的方法,下面是該方法的代碼:

[backcolor=rgba(255, 255, 255, 0.5)][backcolor=white !important][size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em][size=1em]function startList() {
[size=1em]  const item = sources.shift();
[size=1em]  if (item) {
[size=1em]    grab(item);
[size=1em]  } else {
[size=1em]    if (newData.length) {
[size=1em]      const subject = '新的活動線報';
[size=1em]      let content = '\r\n\r\n';
[size=1em]      newData.forEach(item => {
[size=1em]        const { title, url } = item;
[size=1em]        content += `${title}\r\n\r\n${url}\r\n\r\n`;
[size=1em]      });
[size=1em]      sendMessage(subject, content);
[size=1em]    }
[size=1em]  }
[size=1em]}



[backcolor=rgba(255, 255, 255, 0.5)]這里又出現了一個sendMessage方法,我們抓取到了消息需要推送到我們的手機,推送的話就那些渠道,短信,微信,郵件之類的,郵件的話我們不會經常去看,短信的話成本還是有一些的,最適合的就是郵件了,這里使用的是Server醬來進行微信消息的推送,怎么使用呢?打開網址http://sc.ftqq.com然后登錄,沒有賬號的可以注冊一個,點擊發送消息,我們可以得到我們的SCKEY和調用代碼

https://sc.ftqq.com/SCKEY.send?text=主人服務器又掛掉啦~

[backcolor=rgba(255, 255, 255, 0.5)]然后我們在代碼中簡單的編寫發送代碼:

[backcolor=rgba(255, 255, 255, 0.5)][backcolor=white !important][size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em][size=1em]function sendMessage(title, content) {
[size=1em]  request({
[size=1em]    url: `[size=1em]https://sc.ftqq.com/SCU43320Tb8f1c7232560d9aa45f9b3c60b3d99ad5c4bf326b4df0.send?text=${encodeURIComponent(title)}&desp=${encodeURIComponent(content)}`
[size=1em]  })
[size=1em]}



[backcolor=rgba(255, 255, 255, 0.5)]這樣子我們的要冒爬蟲就基本實現了,下面是所有代碼,包含了一些個人找的比較好的源,但是里面會有垃圾信息,加了一些簡單的過濾,還是有,有興趣的朋友可以再去調調:

[backcolor=rgba(255, 255, 255, 0.5)][backcolor=white !important][size=1em]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em]29

[size=1em]30

[size=1em]31

[size=1em]32

[size=1em]33

[size=1em]34

[size=1em]35

[size=1em]36

[size=1em]37

[size=1em]38

[size=1em]39

[size=1em]40

[size=1em]41

[size=1em]42

[size=1em]43

[size=1em]44

[size=1em]45

[size=1em]46

[size=1em]47

[size=1em]48

[size=1em]49

[size=1em]50

[size=1em]51

[size=1em]52

[size=1em]53

[size=1em]54

[size=1em]55

[size=1em]56

[size=1em]57

[size=1em]58

[size=1em]59

[size=1em]60

[size=1em]61

[size=1em]62

[size=1em]63

[size=1em]64

[size=1em]65

[size=1em]66

[size=1em]67

[size=1em]68

[size=1em]69

[size=1em]70

[size=1em]71

[size=1em]72

[size=1em]73

[size=1em]74

[size=1em]75

[size=1em]76

[size=1em]77

[size=1em]78

[size=1em]79

[size=1em]80

[size=1em]81

[size=1em]82

[size=1em]83

[size=1em]84

[size=1em]85

[size=1em]86

[size=1em]87

[size=1em]88

[size=1em]89

[size=1em]90

[size=1em]91

[size=1em]92

[size=1em]93

[size=1em]94

[size=1em]95

[size=1em]96

[size=1em]97

[size=1em]98

[size=1em]99

[size=1em]100

[size=1em]101

[size=1em]102

[size=1em]103

[size=1em]104

[size=1em]105

[size=1em]106

[size=1em]107

[size=1em]108

[size=1em]109

[size=1em]110

[size=1em]111

[size=1em]112

[size=1em]113

[size=1em]114

[size=1em]115

[size=1em]116

[size=1em]117

[size=1em]118

[size=1em]119

[size=1em]120

[size=1em]121

[size=1em]122

[size=1em]123

[size=1em]124

[size=1em]125

[size=1em]126

[size=1em]127

[size=1em]128

[size=1em]129

[size=1em]130

[size=1em]131

[size=1em]132

[size=1em]133

[size=1em]134

[size=1em]135

[size=1em]136

[size=1em]137

[size=1em][size=1em]const path = require('path');
[size=1em]const fs = require('fs-extra');
[size=1em]const request = require('request');
[size=1em]const cheerio = require('cheerio');
[size=1em]const iconv = require('iconv-lite');

[size=1em]const FILTER_WORDS = ['虛擬', '軟件', '破解', '搬磚', '考核', '道具', '王者榮耀', '原創修改', '作圖必備', '技術', '制作', '神器', '關閉', '黃了'];

[size=1em]const READED_PATH = path.join(__dirname, 'readed.json');
[size=1em]const newData = [];

[size=1em]const sources = [
[size=1em]  {
[size=1em]    url: '[size=1em]https://www.zhuanyes.com/',
[size=1em]    selector: '#threadlisttableid a'
[size=1em]  },
[size=1em]  {
[size=1em]    url: '[size=1em]http://www.wz169.com/category/xianbao/',
[size=1em]    selector: '#main a'
[size=1em]  },
[size=1em]  {
[size=1em]    url: '[size=1em]https://www.work28.com/category-4.html',
[size=1em]    selector: '.listbody ul a'
[size=1em]  },
[size=1em]  {
[size=1em]    url: '[size=1em]https://www.xiaozuan8.com/xianbao/',
[size=1em]    selector: '#postlist_blog .post-title_blog a'
[size=1em]  },
[size=1em]  {
[size=1em]    url: '[size=1em]http://www.79tao.com/forum-44-1.html',
[size=1em]    selector: 'tbody[id^="normalthread_"] .new a.xst',
[size=1em]  },
[size=1em]  {
[size=1em]    url: '[size=1em]http://www.wz169.com/category/xianbao/',
[size=1em]    selector: '#main h2.list-title a'
[size=1em]  },
[size=1em]  // {
[size=1em]  //   url: '[size=1em]https://www.fxzhan.com/?cate=2',
[size=1em]  //   selector: '.mainlist .wx_li a'
[size=1em]  // },
[size=1em]  {
[size=1em]    url: '[size=1em]http://8ym.cn/RptList',
[size=1em]    selector: '.list-group .list-group-item'
[size=1em]  },
[size=1em]  {
[size=1em]    url: '[size=1em]https://www.haojiyou.la/html/newslist-14.html',
[size=1em]    selector: '.news-left ul li span a'
[size=1em]  }
[size=1em]];

[size=1em]function checkIsRead(readData, url) {
[size=1em]  return readData.indexOf(url) !== -1;
[size=1em]}

[size=1em]function grab(item) {
[size=1em]  const { url, selector, headers = {} } = item;
[size=1em]  const oldData = fs.readJsonSync(READED_PATH);
[size=1em]  const grabUrl = url;
[size=1em]  request({
[size=1em]    url,
[size=1em]    encoding: null,
[size=1em]    headers: Object.assign({}, headers, {
[size=1em]      userAgent: 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
[size=1em]    })
[size=1em]  }, (err, response, body) => {
[size=1em]    if (err) {
[size=1em]      startList();
[size=1em]    } else {
[size=1em]      const newBody = item.isGBK ? iconv.decode(body,'gb2312').toString() : body.toString();
[size=1em]      const $ = cheerio.load(newBody);
[size=1em]      const list = $(selector);
[size=1em]      list.each(function() {
[size=1em]        const _this = $(this);
[size=1em]        let url = _this.attr('href');
[size=1em]        if (!/^https?/.test(url)) {
[size=1em]          url = joinPath(grabUrl, url);
[size=1em]        }
[size=1em]        const title = _this.text().replace(/\d{2}:?\d{2}:?\d{2}/g, '');
[size=1em]        const isRead = checkIsRead(oldData, url);
[size=1em]        if (!isRead && title.trim() && !RegExp(FILTER_WORDS.join('|')).test(title)) {
[size=1em]          oldData.unshift(url);
[size=1em]          newData.push({
[size=1em]            title,
[size=1em]            url
[size=1em]          });
[size=1em]        }
[size=1em]      });
[size=1em]      fs.writeJsonSync(READED_PATH, oldData);
[size=1em]      startList();
[size=1em]    }
[size=1em]  });
[size=1em]}

[size=1em]function sendMessage(title, content) {
[size=1em]  request({
[size=1em]    url: `[size=1em]https://sc.ftqq.com/SCU43320Tb8f1c7232560d9aa45f9b3c60b3d99ad5c4bf326b4df0.send?text=${encodeURIComponent(title)}&desp=${encodeURIComponent(content)}`
[size=1em]  })
[size=1em]}

[size=1em]function startList() {
[size=1em]  const item = sources.shift();
[size=1em]  if (item) {
[size=1em]    grab(item);
[size=1em]  } else {
[size=1em]    if (newData.length) {
[size=1em]      const subject = '新的活動線報';
[size=1em]      let content = '\r\n\r\n';
[size=1em]      newData.forEach(item => {
[size=1em]        const { title, url } = item;
[size=1em]        content += `${title}\r\n\r\n${url}\r\n\r\n`;
[size=1em]      });
[size=1em]      sendMessage(subject, content);
[size=1em]    }
[size=1em]  }
[size=1em]}

[size=1em]function start() {
[size=1em]    startList();
[size=1em]}

[size=1em]function joinPath(url, path) {
[size=1em]  const pathArr = url.split(/(?<!\/)\/(?!\/)/);
[size=1em]  if (path[0] === '/') {
[size=1em]    return pathArr[0] + path;
[size=1em]  } else {
[size=1em]    if (path.substr(0, 2) === './') {
[size=1em]      pathArr.pop();
[size=1em]      return pathArr.join('/') + '/' + path.substr(2);
[size=1em]    } else {
[size=1em]      const backArr = path.split('../');
[size=1em]      pathArr.length = pathArr.length - backArr.length;
[size=1em]      return pathArr.join('/') + '/' + backArr[backArr.length - 1];
[size=1em]    }
[size=1em]  }
[size=1em]}

[size=1em]start();



[backcolor=rgba(255, 255, 255, 0.5)]最后還有一個問題就是如何定時抓取呢?我們只需要簡單的設置定時任務就可以了,至于定時怎么設,百度一下鋪天蓋地,這里就不多做討論了,如果想更實時一點,抓取間隔時間可以設的短一點,這個可以看自己情況而定。

[backcolor=rgba(255, 255, 255, 0.5)]好了,一個會賺錢的爬蟲就完成了


您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

小黑屋|Archiver|賺客吧APP下載|賺客吧-線報網 ( 閩ICP備19021387號-3 )

GMT+8, 2020-8-30 12:28 , Processed in 0.279364 second(s), 10 queries , MemCached On.

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回復 返回頂部 返回列表
腾讯分分彩四星组选24