爬虫
介绍通过之前的实践,已经完成了小说内容定时爬取,以及小说内容的入库操作等。可是只有这些,我们还是看不了小说,因为它只在我们的数据库里。
那么今天,就简单的做几个api接口,将数据开放出来。这样只要调用api接口就能拿出数据展示了。这里面的api我就偷懒使用beego的库来实现了吧
我这边的api接口也不会太多,目前计划只做3个:
获取小说列表
获取指定小说章节列表
获取指定章节详情内容
spider代码调整
spider/spider.go
package spiderimport ( "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 mainimport ( _ "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 => 章节idfunc (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 routersimport( "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
章节列表
http://localhost:8089/v1/book/chapter?id=950
章节详情
源码完