王者榮耀故事站小程式(nuxt + 小程式)

naice發表於2019-02-16

前言

一直想學習開發一款小程式,無奈拖延至今,恰逢王者榮耀週年慶,然後本人對王者英雄的人物、配音比較感興趣,就有開發一款王者榮耀故事站的小程式的念頭。想要了解故事背景就直接開啟小程式就好了。

ps: 因為是業餘時間做的,所以 pc 端的爬蟲資料展示方面就有點粗糙。

技術棧

小程式 + nuxt + koa2 + vue2.0 + vuex + nginx + pm2

小程式效果圖

WechatIMG2252.jpeg

線上體驗

WechatIMG2252.jpeg

pc 爬蟲效果圖

44
44
44
44

線上地址

http://storyweb.naice.me/
(如果覺得很慢的同學不是你們的網速的問題,是我的伺服器配置太渣了2333)

首先說下爬蟲資料

資料爬蟲都是從王者榮耀故事站官網來爬取的,然後直接用 next/koa 作為後臺,用cheerio模組和request-promise模組基本就可以爬到我們想要的資料了,有時候爬取出來的資料回事亂碼(非 utf-8的)我們就藉助iconv模組去轉成我們想要的中文字元。這些模組說明文件在相應的 gihub中都說的很詳細。就不一一介紹。
下面舉例一下爬蟲英雄列表首頁的過程,都註釋在程式碼裡面

// 引入相應的模組
import rp from `request-promise`
import cheerio from `cheerio`
import { writeFileSync } from `fs`

const Iconv = require(`iconv`).Iconv
const iconv = new Iconv(`GBK`, `UTF-8`)

// request 國外網站的時候使用本地的 VPN
// import Agent from `socks5-http-client/lib/Agent`

// 爬取英雄列表
const getHeroStory = async() => {
  // request-promise的配置
  const options = {
    uri: `https://pvp.qq.com/act/a20160510story/herostory.htm`,
    // agentClass: Agent,
    // agentOptions: {
    //   socksHost: `localhost`,
    //   socksPort: 1080 // 本地 VPN 的埠,這裡用的 shadowsocks
    // },
    transform: body => cheerio.load(body) // 轉成相應的爬蟲
  }
  // 爬取導航複製給cheerio的$物件
  const $ = await rp(options)
  let navArr = []
  let heroList = []
  $(`#campNav li`).each(function () {
    // 分析節點拿到資料
    const type = $(this).attr(`data-camptype`)
    const text = $(this).find(`a`).text()
    // push 到navArr陣列中
    navArr.push({ type, text })
  })
  // 爬取英雄列表
  const hreodata = await rp({
    uri: `https://pvp.qq.com/webplat/info/news_version3/15592/18024/23901/24397/24398/m17330/list_1.shtml`
  })
  // 資料處理
  let str = hreodata.replace(`createHeroList(`, ``)
  str = str.substr(0, str.length - 1)
  let r = JSON.parse(str)
  heroList = r.data.filter(item => item)

  let result = {
    nav: navArr,
    heroList
  }
  // 寫入檔案
  writeFileSync(`./server/crawerdb/heroList.json`, JSON.stringify(result, null, 2), `utf-8`)

  return result
}

// 跟去英雄 id,和 url 爬取英雄的詳細介紹
const getHeroDatail = async(url, _id) => {
  // 配置
  const option = {
    encoding: null,
    url
  }
  // 爬取英雄詳情
  const $ = await rp(option).then(body => {
    // 字元亂碼處理
    var result = iconv.convert(new Buffer(body, `binary`)).toString()
    return cheerio.load(result)
  })
  // 這裡拿到$之後就像 jq那樣子,根據文件就可以進行爬蟲的資料處理了
  // 下面都是資料處理
  let heroName = ``
  let heroDetail = []
  let ht = ``
  let hc = ``
  if ($(`#heroStory`).length) {
    heroName = $(`.hero_name pf`).text()
    $(`#heroStory p`).each(function () {
      let text = $(this).text().trim()
      heroDetail.push({
        type: `text`,
        text: text
      })
    })
  } else if ($(`.textboxs`).length) {
    $(`.textboxs p`).each(function () {
      if ($(this).find(`img`).length) {
        let src = $(this).find(`img`).attr(`src`)
        heroDetail.push({
          type: `img`,
          text: `https:` + src
        })
      } else {
        let text = $(this).text().trim()
        heroDetail.push({
          type: `text`,
          text: text
        })
      }
    })
  }
  let hStr = ($(`#history_content`).text()).replace(/(^s+)|(s+$)/g, ``);

  if (hStr.length > 0) {
    ht = $(`.history_story h3`).text()
    hc = $(`#history_content`).text()
  }
  let result = {
    heroName,
    heroDetail,
    historyTitle: ht,
    historyContent: hc
  }
  // 寫入檔案
  writeFileSync(`./server/crawerdb/herodetail` + _id + `.json`, JSON.stringify(result, null, 2), `utf-8`)
  return result
}

export default {
  getHeroStory,
  getHeroDatail
}

然後在 koa裡面配置好路由就可以一步步爬取資料了

nuxt

Nuxt.js 是一個基於 Vue.js 的通用應用框架。通過對客戶端/服務端基礎架構的抽象組織,Nuxt.js 主要關注的是應用的 UI渲染。我們的目標是建立一個靈活的應用框架,你可以基於它初始化新專案的基礎結構程式碼,或者在已有 Node.js 專案中使用 Nuxt.js。Nuxt.js 預設了利用Vue.js開發服務端渲染的應用所需要的各種配置。

根據文件 page 下面的結構就是對應的 vue 的路由結構,然後配置好nuxt.config.js你所需要模組、外掛、webpack 配置等等都有很好的中文文件說明。會 vue的同學,去看一下官網就可以大概有個很好的瞭解了。
下面是整個專案的目錄結構

.nuxt/
build/  ---打包釋出
components/ ---元件
layout/   ---佈局
pages/    ---對應的路由
--| about.vue/
--| music.vue/
--| word.vue/
--| skin/
--| index.vue
--| ....
server/  --對應的koa 後臺
static/  ---靜態資源
store/  --vuex

小程式

這是我第一個小程式。所以一開始看文件,寫起資料繫結的時候,會有種跟 vue 的異曲同工的感覺.
下面是官荒的小例子

demo.wxml

<view> Hello {{name}}! </view>
<view wx:for="{{array}}">
  {{index}}: {{item.message}}
</view>

demo.js

Page({
  data: {
    name: `小程式`,
    array: [{
      message: `foo`,
    }, {
      message: `bar`
    }]
  }
})

是不是太熟悉了????當然裡面實現的技術還是想差別很大的,想去詳細的瞭解,我覺得《一起脫去小程式的外套 – 微信小程式架構解析》這篇文章,很是不錯,我初學的時候,是先體驗一番小程式的demo,然後直接動手(光看不動瞎扯淡),再去深入瞭解原理、pages 的生命週期,邏輯處理、框架、元件、api 等等,理解了這些之後,後面就很容易啦!!

附一張小程式的執行生命週期圖(來源於遇見大神的文章),用來理解小程式的整個執行過程
44

github

小程式:https://github.com/naihe138/h…

小程式後臺爬蟲: https://github.com/naihe138/h…

部落格文章:https://blog.naice.me/

如果大家覺得有用的話,求一個閃晶晶的 start ,謝謝各位大佬

相關文章