Golang 简单爬虫实现 · API接口开发

本文为转载,原文:Golang 简单爬虫实现 · API接口开发

爬虫

介绍

通过之前的实践,已经完成了小说内容定时爬取,以及小说内容的入库操作等。可是只有这些,我们还是看不了小说,因为它只在我们的数据库里。

那么今天,就简单的做几个api接口,将数据开放出来。这样只要调用api接口就能拿出数据展示了。这里面的api我就偷懒使用beego的库来实现了吧

我这边的api接口也不会太多,目前计划只做3个:

  1. 获取小说列表

  2. 获取指定小说章节列表

  3. 获取指定章节详情内容

实现

spider代码调整

由于我们的 main.go作为入口代码文件,所以,这边打算将之前的爬取数据的代码移到spider/spider.go文件中。
改版之后的spider.go代码如下:

package spider

import (
    "errors"

    "github.com/Chain-Zhang/igo/ilog"
    "github.com/Chain-Zhang/igo/conf"
    "github.com/robfig/cron"

    "ispider/models"
)

type SBook struct{
    Name string
    Image string
    Url string
    Chapters []*SChapter
}

type SChapter struct{
    Title string
    Url string
    Order int
    Pre int
    Next int
    Content string
}

type Spider interface{
    SpiderUrl(url string) error
}

func NewSpider(from string) (Spider, error){
    switch from{
    case "booktxt":
        return new(BookTextSpider), nil
    default:
        return nil, errors.New("系统暂未处理该类型的配置文件")
    }
}

func Start(){
    ilog.AppLog.Info("service start")
    c := cron.New()
    spec := conf.AppConfig.GetString("task.spec")
    ilog.AppLog.Info("spec: ",spec)
    c.AddFunc(spec,getBook)
    c.Start()
    select{}
}

func getBook(){
    ilog.AppLog.Info("spider start")
    books, _ := models.GetBookList("status", 1)
    for _, book := range books{
        go func(book *models.Book){
            s, err := NewSpider(book.From)
            if err != nil{
                ilog.AppLog.Error("new Spider error: ", err.Error())
                return
            }
            err = s.SpiderUrl(book.Url)
            if err != nil{
                ilog.AppLog.Error("new Document error: ", err.Error())
            }
            ilog.AppLog.Info(book.Name, "已爬取完毕")
        }(book)
    }
}

api文件列表

既然使用了beego的库,那么,就在原有的目录基础上先建一些相关的目录和文件吧

controllers  //controllers包
----base.go  //controller基类简单封装
----book.go  //book的controller实现

routers      //routers包
----router.go //路由分配,

main.go  //入口代码文件

没错,我们的api接口实现就是这么几个文件就能搞定。

代码实现

main.go

main.go文件作为入口文件,所以这里写的并不复杂,只需要调用2个函数,以及初始化路由即可。代码如下:

package main

import (
    _ "ispider/routers"  //执行routers包的init函数
    "ispider/spider"
    "github.com/astaxie/beego"
    "github.com/Chain-Zhang/igo/ilog"
)

func main() {
    ilog.AppLog.Info("start")
    go spider.Start()   //异步执行爬虫协程
    beego.Run(":8089")  //开启api服务
}

controllers

base.go

base.go作为所有controllers的基类,所以需要封装一下公用的函数,提高代码复用率。

package controllers

import(
    "github.com/astaxie/beego"
)

// json 返回错误码
const (
    MSG_OK  = 0   // 成功
    MSG_ERR = -1  // 失败
)

// 基类
type BaseController struct{
    beego.Controller
}

// 固定返回的json数据格式
// msgno: 错误码
// msg: 错误信息
// data: 返回数据
func (self *BaseController) toJson (msgno int, msg string, data interface{}){
    out := make(map[string]interface{})
    out["status"] = msgno
    out["msg"] = msg
    out["data"] = data
    self.Data["json"] = out
    self.ServeJSON()
}

从代码中可知,目前基类中只实现了一个格式化输出json的功能。
其他功能以后待扩展。

book.go

book.go就是针对小说的一个控制器了。代码如下:

package controllers

import(
    "ispider/models"
)

type BookController struct{
    BaseController
}

//获取小说列表
func (self *BookController) GetAll(){
    books, _ := models.GetBookList()
    self.toJson(MSG_OK, "成功", books)
}

// 分页获取指定小说的章节列表, 每页10条
// url参数:bookid => 小说id; page => 页码
func (self *BookController) GetChapters(){
    bookid, err := self.GetInt("bookid")
    if err != nil{
        self.toJson(MSG_ERR, err.Error(), nil)
    }
    page, err := self.GetInt("page")
    if err != nil{
        self.toJson(MSG_ERR, err.Error(), nil)
    }
    chapters, _ := models.GetChapterPage(page, 10, "book_id",bookid)
    self.toJson(MSG_OK, "success", chapters)
}

// 获取指定章节详细信息
// url参数: id => 章节id
func (self *BookController) GetChapter(){
    id, err := self.GetInt("id")
    if err != nil{
        self.toJson(MSG_ERR, err.Error(), nil)
    }
    chapter, err := models.GetChapterById(id)
    if err != nil{
        self.toJson(MSG_ERR, err.Error(), nil)
    }
    self.toJson(MSG_OK, "success", chapter)
}

从代码中可知,这个controller也比较简单,总共实现了之前所说的三个api接口的action。具体可见代码注释。

routers

既然controllers已经完成。那么接下来就是进行路由配置了。

package routers

import(
    "github.com/astaxie/beego"
    "ispider/controllers"
)

func init() {
    ns := beego.NewNamespace("/v1",
        beego.NSNamespace("/book",
            // /v1/book  获取小说列表
            beego.NSRouter("/", &controllers.BookController{}, "get:GetAll"),
            // /v1/book/getchapters?bookid=xxx&page=1  获取小说章节列表
            beego.NSRouter("/getchapters", &controllers.BookController{}, "get:GetChapters"),
            // /v1/book/chapter?id=xxx  获取章节内容
            beego.NSRouter("/chapter", &controllers.BookController{}, "get:GetChapter"),
        ),
    )
    beego.AddNamespace(ns)
}

好啦,如今路由耶配合了,那么,这编码也就结束了。

运行测试

接下来就是见证奇迹的时刻了。跑起来看看吧。

控制台进入代码根目录,执行命令bee run:

bee run

然后浏览器输入地址:http://localhost:8089/v1/book

小说列表

在输入地址:http://localhost:8089/v1/book/getchapters?bookid=2&page=5

章节列表

再输入章节详情的url: http://localhost:8089/v1/book/chapter?id=950

章节详情

源码

本文源码

转载请注明出处:
Golang 简单爬虫实现 · API接口开发

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容