用typescript開發爬蟲過程實踐

demo碼雲git地址:  https://gitee.com/jamesview/jspider

用typescript開發爬蟲過程實踐

最近剛學typescript,想着能用來作點什麼,順便也練練手,加之最近也有個想法,前提是須要解決數據來源的問題,因此嘗試一下能不能用ts來寫一個爬蟲,而後存到數據庫裏面爲我所用,下面就是個人實踐過程html

配置開發環境

全局安裝typescriptnode

npm install -g typescript

建立項目文件夾mysql

mkdir ts-spider

進入該文件夾之後初始化項目ios

npm init -y

下面要安裝一下項目中用到的模塊git

  • axios (網絡請求)
  • cheerio (提供jQuery Selector的解析能力)
  • mysql (數據庫交互)
npm i --save axios cheerio mysql

相應的,要安裝一下對應的類型聲明模塊github

npm i -s @types/axios --save  
npm i -s @types/cheerio --save 
npm i -s @types/mysql --save

其實axios已經自帶類型聲明,因此不安裝也是能夠的sql

下面安裝一下項目內的typescript(必須走這一步)typescript

npm i --save typescript

用vscode打開項目,在根目錄下新建一個tsconfig.json文件,加入一下配置項數據庫

{ 
    "compilerOptions": { 
        "target": "ES6", 
        "module": "commonjs", 
        "noEmitOnError": true, 
        "noImplicitAny": true, 
        "experimentalDecorators": true, 
        "sourceMap": false, 
     // "sourceRoot": "./", 
        "outDir": "./out" 
    }, 
    "exclude": [ 
        "node_modules" 
    ] 
}

到這裏咱們的環境搭建算基本完成了,下面咱們來測試下npm

開發環境測試

在項目根目錄下建立一個api.ts文件,寫入如下代碼

import axios from 'axios'
 
/**網絡請求 */
export const remote_get = function(url: string) { 
  const promise = new Promise(function (resolve, reject) { 
    axios.get(url).then((res: any) => {
        resolve(res.data);
    }, (err: any) => {
        reject(err);
    });
  });
  return promise;
}

建立一個app.ts文件,寫入如下代碼

import { remote_get } from './api'

const go = async () => { 
    let res = await remote_get('http://www.baidu.com/'); 
    console.log(`獲取到的數據爲: ${res}`);
} 
go();

執行一下命令

tsc

咱們發現項目根目錄想多了一個/out文件夾,裏面是轉換後的js文件

咱們執行一下

node out/app

輸出相似這樣,就表明咱們的爬蟲已經爬到了這個網頁,環境測試已經經過了!接下來咱們嘗試一下抓取其中的數據

 

 

分析網頁並抓取數據

咱們將app.ts重構一下,引入cheerio,開始抓取咱們須要的數據,固然了,此次咱們換一下目標,咱們抓取一下豆瓣上面的的數據

前面也提到了cheerio提供了jQuery Selector的解析能力,關於它的具體用法,能夠點擊這裏查看

import { remote_get } from './api'
import * as cheerio from 'cheerio'

const go = async () => { 
  const res: any = await remote_get('https://www.douban.com/group/szsh/discussion?start=0');
  // 加載網頁
  const $ = cheerio.load(res);
  let urls: string[] = [];
  let titles: string[] = [];
  // 獲取網頁中的數據,分別寫到兩個數組裏面
  $('.olt').find('tr').find('.title').find('a').each((index, element) => { 
      titles.push($(element).attr('title').trim()); 
      urls.push($(element).attr('href').trim()); 
  })
  // 打印數組
  console.log(titles, urls);
} 
go(); 
複製代碼

這段代碼是獲取豆瓣上小組話題和對應的連接,而後寫入數組裏面,分別打印出來。咱們跑一下代碼,看看輸出

 

 

能夠看到已經獲取到咱們想要的數據了。接下來咱們嘗試把這些數據寫入到數據庫裏面

將數據寫入數據庫

開始的時候實際上是想把數據寫到MongoDB裏面,可是考慮到本身對這個還不太熟,和本身手頭的體驗版服務器那一點點可憐的空間,最後仍是放棄了,仍是決定先嚐試寫到mysql數據庫裏面

咱們先本地安裝一個mysql數據庫,安裝過程就不詳細說了,安裝完後在本地數據庫中新建一個表

 

 

在項目根目錄下添加util.ts文件,寫入一下代碼

import * as mysql from 'mysql'

/* 延時函數 */
export function sleep(msec: number) {
  return new Promise<void>(resolve => setTimeout(resolve, msec));
}

/**
 * 封裝一個數據庫鏈接的方法
 * @param {string} sql SQL語句
 * @param arg SQL語句插入語句的數據
 * @param callback SQL語句的回調
 */
export function db(sql: string, arg: any, callback?: any) {
  // 1.建立鏈接
  const config = mysql.createConnection({
      host: 'localhost', // 數據庫地址
      user: 'root', // 數據庫名
      password: '', // 數據庫密碼
      port: 3306, // 端口號
      database: 'zhufang' // 使用數據庫名字
  });
  // 2.開始鏈接數據庫
  config.connect();
  // 3.封裝對數據庫的增刪改查操做
  config.query(sql, arg, (err:any, data:any) => {
      callback(err, data);
  });
  // 4.關閉數據庫
  config.end();
}
複製代碼

以上咱們已經封裝好了一個數據庫鏈接的方法,其中包含了數據庫的配置信息,下面咱們修改app.ts文件,引入咱們封裝好的db模塊,並寫入數據的操做代碼

import { remote_get } from './api'
import * as cheerio from 'cheerio'
import { sleep, db } from './util'

const go = async () => { 
  const res: any = await remote_get('https://www.douban.com/group/szsh/discussion?start=0');
  // 加載網頁
  const $ = cheerio.load(res);
  let urls: string[] = [];
  let titles: string[] = [];
  // 獲取網頁中的數據,分別寫到兩個數組裏面
  $('.olt').find('tr').find('.title').find('a').each((index, element) => { 
      titles.push($(element).attr('title').trim()); 
      urls.push($(element).attr('href').trim()); 
  })
  // 打印數組
  console.log(titles, urls);
  // 往數據庫裏面寫入數據
  titles.map((item, index) => {
    db('insert into info_list(title,url) values(?,?)', [item, urls[index]], (err: any, data: any) => {
        if(data){
          console.log('提交數據成功!!')
        }
        if (err) {
            console.log('提交數據失敗')
        }
    })
  })
} 
go(); 
複製代碼

這裏咱們往數據庫中插入title數組和urls數組的數據。跑一下代碼,看了輸出沒有問題,咱們看下數據庫

 

 

數據已經寫入了!到這裏咱們的此次實踐就告一段落

下面考慮的是爬取數據過快的延時機制,和如何分頁獲取數據,如何獲取爬到的連接對應的詳細信息,功能模塊化等等,這裏就不細說了

參考文檔

https://cloud.tencent.com/info/d0dd52a4a2b1f90055afe4fac4dcd76b.html

https://hpdell.github.io/%E7%88%AC%E8%99%AB/crawler-cheerio-ts/

相關文章
相關標籤/搜索