2

基于gathertool高并发抓取阳光高考招生简章

 3 years ago
source link: https://studygolang.com/articles/35027
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

基于gathertool高并发抓取阳光高考招生简章

mange · 1天之前 · 116 次点击 · 预计阅读时间 6 分钟 · 大约8小时之前 开始浏览    

golang爬虫高并发抓取阳光高考招生简章

一级页面 学校列表 https://gaokao.chsi.com.cn/zsgs/zhangcheng/listVerifedZszc--method-index,lb-1,start-0.dhtml

二级页 招生简章列表 https://gaokao.chsi.com.cn/zsgs/zhangcheng/listZszc--schId-5.dhtml

三级页 招生章程内容 https://gaokao.chsi.com.cn/zsgs/zhangcheng/listVerifedZszc--infoId-2708104715,method-view,schId-5.dhtml

在这里插入图片描述

抓取框架 gathertool

框架地址: https://github.com/mangenotwork/gathertool 框架下载: go get github.com/mangenotwork/gathertool 介绍: 轻量级爬虫,接口测试,压力测试框架, 提高开发对应场景的golang程序。 框架文档: https://380949.baklib-free.com/

package main

import (
    "fmt"
    "log"
    "time"

    "github.com/PuerkitoBio/goquery"
    gt "github.com/mangenotwork/gathertool"
)

var (
    PG1Queue = gt.NewQueue() // 一级页面抓取任务队列
    PG2Queue = gt.NewQueue() // 二级页面抓取任务队列
    PG3Queue = gt.NewQueue() // 三级页面抓取任务队列
    host = "127.0.0.1"
    port = 3306
    user = "root"
    password = "root123"
    database = "spider"
    tableName = "yggk_zszc_1"
)

func init(){
    gt.NewMysqlDB(host, port, user, password, database)
    err := gt.MysqlDB.Conn()
    if err != nil{
        log.Panic("数据库初始化失败")
    }
    //初始化表
    gt.MysqlDB.NewTable(tableName, map[string]string{
        "school_name": "varchar(30)",
        "zszcName" : "varchar(50)",
        "fbTime" : "varchar(30)",
        "url" : "varchar(200)",
        "content": "text",
    })
}

// 全量抓取
func main(){
    // 一共 29页
    for p:=0; p<30;p++{
        pg1 := "https://gaokao.chsi.com.cn/zsgs/zhangcheng/listVerifedZszc--method-index,lb-1,start-%d.dhtml"
        PG1Queue.Add(&gt.Task{
            Url: fmt.Sprintf(pg1, p*100),
        })
    }
    //并发执行一级页面
    gt.StartJobGet(50,PG1Queue,
        gt.SucceedFunc(Pg1Succeed),//请求成功后执行的方法
        gt.RetryFunc(Retry),
        gt.FailedFunc(Fail),
    )
    log.Println(" 并发执行一级页面 完成")
    //并发执行二级页面
    gt.StartJobGet(50,PG2Queue,
        gt.SucceedFunc(Pg2Succeed),//请求成功后执行的方法
        gt.RetryFunc(Retry),
        gt.FailedFunc(Fail),
    )
    log.Println(" 并发执行二级页面 完成")
    //并发执行三级页面
    gt.StartJobGet(100,PG3Queue,
        gt.SucceedFunc(Pg3Succeed),//请求成功后执行的方法
        gt.RetryFunc(Retry),
        gt.FailedFunc(Fail),
    )
    log.Println(" 并发执行三级页面 完成")

    ////测试第二级页面
    //c,_ := gt.Get("https://gaokao.chsi.com.cn/zsgs/zhangcheng/listZszc--schId-1.dhtml",
    //    gt.SucceedFunc(Pg2Succeed))
    //c.Do()

    //测试第三级页面
    //for i:=0; i<100;i++{
    //    go func(){
    //        c,_ := gt.Get("https://gaokao.chsi.com.cn/zsgs/zhangcheng/listVerifedZszc--infoId-2697675279,method-view,schId-1.dhtml",
    //            gt.SucceedFunc(Pg3Succeed))
    //        c.Do()
    //    }()
    //}
    //time.Sleep(10*time.Second)
}

// 抓取第一级页面成功后
func Pg1Succeed(ctx *gt.Context){
    html := string(ctx.RespBody)
    dom,err := gt.NewGoquery(html)
    if err != nil{
        log.Println(err)
        return
    }
    result := dom.Find("table tbody")
    if len(result.Nodes) < 2{
        log.Println("没有找到table")
    }
    result.Eq(1).Each(func(i int, tr *goquery.Selection){
        tr.Find("td").Each(func(i int, td *goquery.Selection){
            schoolName := td.Text()
            href,_ := td.Find("a").Attr("href")
            log.Println(schoolName, href)
            // 加入二级页面队列
            PG2Queue.Add(&gt.Task{
                Url: "https://gaokao.chsi.com.cn/" + href,
                Data: map[string]interface{}{
                    "school_name":schoolName,
                },
            })
        })
    })
}
// 抓取第二级页面成功后
func Pg2Succeed(ctx *gt.Context){
    html := string(ctx.RespBody)
    dom,err := gt.NewGoquery(html)
    if err != nil{
        log.Println(err)
        return
    }
    result := dom.Find(".zszcdel table tbody")
    //log.Println(result.Html())
    result.Find("tr").Each(func(i int, tr *goquery.Selection){
        td := tr.Find("td")
        zszcName := td.Eq(0).Text()
        href,_ := td.Eq(0).Find("a").Attr("href")
        fbTime := td.Eq(1).Text()
        log.Println(zszcName, href, fbTime)
        ctx.Task.Data["zszcName"] = zszcName
        ctx.Task.Data["fbTime"] = fbTime
        ctx.Task.Data["url"] = "https://gaokao.chsi.com.cn/" + href
        ctx.Task.Url = "https://gaokao.chsi.com.cn/" + href
        PG3Queue.Add(ctx.Task)
    })
}
// 抓取第二级页面成功后
func Pg3Succeed(ctx *gt.Context){
    html := string(ctx.RespBody)
    //log.Println(html)
    dom,err := gt.NewGoquery(html)
    if err != nil{
        log.Println(err)
        return
    }
    content,err := dom.Find(".content").Html()
    log.Println(content, err)
    if err != nil || content == ""{
        log.Println("还给队列")
        PG3Queue.Add(ctx.Task)
    }
    // 写入数据库
    schoolName := gt.StringValue(ctx.Task.Data["school_name"]) // 转换成字符串
    zszcName := gt.StringValue(ctx.Task.Data["zszcName"])
    fbTime := gt.StringValue(ctx.Task.Data["fbTime"])
    err = gt.MysqlDB.Insert(tableName, map[string]interface{}{
        "school_name": gt.CleaningStr(schoolName), // 清理字符串前后空格和换行符等
        "zszcName" : gt.CleaningStr(zszcName),
        "fbTime" : gt.CleaningStr(fbTime),
        "url" : ctx.Task.Data["url"],
        "content": content,
    })
    log.Println(err)
}

func Retry(*gt.Context){
    time.Sleep(2*time.Second)
}
func Fail(ctx *gt.Context){
    log.Println(ctx.Err)
}

在这里插入图片描述


有疑问加站长微信联系(非本文作者))

280

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:701969077


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK