New file |
| | |
| | | package code |
| | | |
| | | import "net/http" |
| | | |
| | | // Code 错误输出数据结构 |
| | | type Code struct { |
| | | Status int `json:"status"` // HTTP 状态 |
| | | Success bool `json:"success"` // 成功或者失败 |
| | | Message string `json:"msg"` // 描述信息 |
| | | } |
| | | |
| | | var ( |
| | | // Success 请求处理成功 |
| | | Success = &Code{http.StatusOK, true, "请求处理成功"} |
| | | // RequestParamError 请求参数错误 |
| | | RequestParamError = &Code{http.StatusBadRequest, false, "请求参数有误"} |
| | | ) |
New file |
| | |
| | | package controllers |
| | | |
| | | import ( |
| | | "fmt" |
| | | "github.com/gin-gonic/gin" |
| | | "github.com/gocolly/colly" |
| | | "log" |
| | | "reptile/code" |
| | | "reptile/util" |
| | | ) |
| | | |
| | | type ReptileControllers struct{} |
| | | |
| | | type FieldSelectorInfo struct { |
| | | Name string `json:"name"` |
| | | Selector string `json:"selector"` |
| | | } |
| | | |
| | | type FieldResult struct { |
| | | Name string |
| | | Value string |
| | | } |
| | | |
| | | type ReptileInfo struct { |
| | | Url string `json:"url"` |
| | | UserName string `json:"userName"` |
| | | UserPassWD string `json:"userPassWD"` |
| | | TitleSelectorStr string `json:"titleSelectorStr"` |
| | | ListSelectorStr string `json:"listSelectorStr"` |
| | | ListRequest bool `json:"listRequest"` |
| | | FspArray []FieldSelectorInfo `json:"fspArray"` |
| | | } |
| | | |
| | | func (rc *ReptileControllers) Reptile(c *gin.Context) { |
| | | var rpif ReptileInfo |
| | | c.BindJSON(&rpif) |
| | | url := rpif.Url |
| | | titleSelectorStr := rpif.TitleSelectorStr |
| | | listSelectorStr := rpif.ListSelectorStr |
| | | fspArray := rpif.FspArray |
| | | listRequest := rpif.ListRequest |
| | | if listRequest == true { |
| | | if url != "" && titleSelectorStr != "" && listSelectorStr != "" && fspArray != nil && len(fspArray) > 0 { |
| | | res := ReptileList(url, titleSelectorStr, listSelectorStr, fspArray) |
| | | util.ResponseFormat(c, code.Success, res) |
| | | return |
| | | } else { |
| | | util.ResponseFormat(c, code.RequestParamError, "请求参数有误") |
| | | return |
| | | } |
| | | } else { |
| | | if url != "" && titleSelectorStr != "" && fspArray != nil && len(fspArray) > 0 { |
| | | res := ReptileNoList(url, titleSelectorStr, fspArray) |
| | | util.ResponseFormat(c, code.Success, res) |
| | | return |
| | | } else { |
| | | util.ResponseFormat(c, code.RequestParamError, "请求参数有误") |
| | | return |
| | | } |
| | | } |
| | | return |
| | | } |
| | | |
| | | func ReptileList(url string, titleSelectorStr string, listSelectorStr string, fspArray []FieldSelectorInfo) interface{} { |
| | | cy := colly.NewCollector() |
| | | rfr := make([]interface{}, 0) |
| | | cy.OnHTML(titleSelectorStr, func(e *colly.HTMLElement) { |
| | | fmt.Println("+++++++++++++++++++++++++++") |
| | | e.ForEach(listSelectorStr, func(i int, ele *colly.HTMLElement) { |
| | | fr := []FieldResult{} |
| | | for _, v := range fspArray { |
| | | fr = append(fr, FieldResult{ |
| | | Name: v.Name, |
| | | Value: ele.ChildText(v.Selector), |
| | | }) |
| | | } |
| | | rfr = append(rfr, fr) |
| | | }) |
| | | }) |
| | | err := cy.Request("GET", url, nil, nil, nil) |
| | | if err != nil { |
| | | log.Fatal("connect error: ", err) |
| | | } |
| | | return rfr |
| | | } |
| | | |
| | | func ReptileNoList(url string, titleSelectorStr string, fspArray []FieldSelectorInfo) []interface{} { |
| | | c := colly.NewCollector() |
| | | rfr := make([]interface{}, 0) |
| | | titleSelectorStr = "body" |
| | | c.OnHTML(titleSelectorStr, func(e *colly.HTMLElement) { |
| | | fmt.Println("+++++++++++++++++++++++++++") |
| | | fr := []FieldResult{} |
| | | for _, v := range fspArray { |
| | | fmt.Println("v.Selector: ", v.Selector) |
| | | fr = append(fr, FieldResult{ |
| | | Name: v.Name, |
| | | Value: e.DOM.Find(v.Selector).Eq(0).Text(), |
| | | }) |
| | | } |
| | | rfr = append(rfr, fr) |
| | | }) |
| | | err := c.Request("GET", url, nil, nil, nil) |
| | | if err != nil { |
| | | log.Fatal("connect error: ", err) |
| | | } |
| | | return rfr |
| | | } |
New file |
| | |
| | | module reptile |
| | | |
| | | go 1.12 |
| | | |
| | | require ( |
| | | github.com/PuerkitoBio/goquery v1.6.0 // indirect |
| | | github.com/antchfx/htmlquery v1.2.3 // indirect |
| | | github.com/antchfx/xmlquery v1.3.3 // indirect |
| | | github.com/gin-gonic/gin v1.6.3 |
| | | github.com/gobwas/glob v0.2.3 // indirect |
| | | github.com/gocolly/colly v1.2.0 |
| | | github.com/kennygrant/sanitize v1.2.4 // indirect |
| | | github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect |
| | | github.com/temoto/robotstxt v1.1.1 // indirect |
| | | google.golang.org/appengine v1.6.7 // indirect |
| | | ) |
New file |
| | |
| | | package main |
| | | |
| | | import ( |
| | | "bytes" |
| | | "encoding/json" |
| | | "fmt" |
| | | "io/ioutil" |
| | | "mime/multipart" |
| | | "net/http" |
| | | "reptile/router" |
| | | "time" |
| | | ) |
| | | |
| | | func main() { |
| | | r := router.NewRouter() |
| | | r.Run("0.0.0.0:7070") |
| | | } |
| | | |
| | | func GetLoginToken(method string, url string, parama []byte) (buf []byte, err error) { |
| | | //defer elapsed("page")() |
| | | timeout := time.Duration(100 * time.Second) |
| | | client := http.Client{ |
| | | Timeout: timeout, |
| | | } |
| | | //loginInfo :=`{"login":"stybd","password":"suntianyu2486"}` |
| | | p := new(bytes.Buffer) |
| | | w := multipart.NewWriter(p) |
| | | |
| | | content_type := w.FormDataContentType() |
| | | //w.WriteField("username","basic") |
| | | //w.WriteField("password","basic2019") |
| | | //w.Close() |
| | | |
| | | //logif := "login=stybd,password=suntianyu2486" |
| | | |
| | | request, err := http.NewRequest(method, url, p) |
| | | request.Header.Set("Content-Type", content_type) |
| | | if err != nil { |
| | | fmt.Println("build request fail !") |
| | | return nil, err |
| | | } |
| | | |
| | | resp, err := client.Do(request) |
| | | if err != nil { |
| | | fmt.Println("request error: ", err) |
| | | return nil, err |
| | | } |
| | | |
| | | defer resp.Body.Close() |
| | | body, err := ioutil.ReadAll(resp.Body) |
| | | if err != nil { |
| | | fmt.Println(err) |
| | | return nil, err |
| | | } |
| | | var info interface{} |
| | | json.Unmarshal(body, &info) |
| | | fmt.Println("access_token: ", info) |
| | | fmt.Println("body: ", resp.StatusCode) |
| | | return body, nil |
| | | } |
New file |
| | |
| | | package router |
| | | |
| | | import ( |
| | | "github.com/gin-gonic/gin" |
| | | "reptile/controllers" |
| | | ) |
| | | |
| | | func NewRouter() *gin.Engine { |
| | | r := gin.Default() |
| | | |
| | | reptile := new(controllers.ReptileControllers) |
| | | |
| | | urlPrefix := "/basic/api-v" |
| | | |
| | | reptileApi := r.Group(urlPrefix + "/reptile") |
| | | { |
| | | reptileApi.POST("/reptile", reptile.Reptile) |
| | | } |
| | | return r |
| | | } |
New file |
| | |
| | | package util |
| | | |
| | | import ( |
| | | "github.com/gin-gonic/gin" |
| | | "reptile/code" |
| | | ) |
| | | |
| | | // |
| | | // ResponseFormat 返回数据格式化 |
| | | func ResponseFormat(c *gin.Context, respStatus *code.Code, data interface{}) { |
| | | if respStatus == nil { |
| | | respStatus = code.RequestParamError |
| | | } |
| | | c.JSON(respStatus.Status, gin.H{ |
| | | "code": respStatus.Status, |
| | | "success": respStatus.Success, |
| | | "msg": respStatus.Message, |
| | | "data": data, |
| | | }) |
| | | return |
| | | } |