首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Let's Go!你输入关键字,我给你b站视频表!

Let's Go!你输入关键字,我给你b站视频表!

作者头像
公众号guangcity
发布2021-07-09 15:52:38
6090
发布2021-07-09 15:52:38
举报
文章被收录于专栏:光城(guangcity)光城(guangcity)

Let's Go!你输入关键字,我给你b站视频表!

0.导语

今天主要是来练习一下Go的语法,之前做过Python爬虫,那放到Go里面如何搞呢?

今天就以b站为例,当输入关键字时,能够抓取出该关键字所对应的所有视频信息。

具体对应如下图所示:

最终效果,如下表所示:

1.分析

分析过程比较简单,直接就是右键检查网络,切换页面,看看哪个url变化,并且对应到页面数据,结果发现请求地址是;

https://api.bilibili.com/x/web-interface/search/type?context=&page=4&order=&keyword=golang&duration=&tids_1=&tids_2=&from_source=&from_spmid=333.337&__refresh__=true&_extra=&search_type=video&highlight=1&single_column=0

里面有很多参数,我们可以去掉一些参数,对结果也不影响,例如:排序之类的,最后得到简化的api接口:

https://api.bilibili.com/x/web-interface/search/type?page=2&keyword=golang&search_type=video

现在根据这个接口,可以发现可变参数是:page与keyword,也就是说我只要传递了搜索关键字与第几页,便可以拿到这个数据,在页面中,我们可以知道是get请求,返回了一个json数据。到此,我们便可以开始敲代码实现了。

2.goquery

这次采用的爬虫库为goquery:

https://github.com/PuerkitoBio/goquery

安装:

$ go get github.com/PuerkitoBio/goquery

那么便可以写出如下demo:

func (b BilCrawl) DoCrawler() {
 numPages := 1
 allRsp := []Header{}
 for i := b.Page; i <= numPages; i++ {
  var url = b.Url + "&keyword=" + b.Keyword + "&page=" + strconv.Itoa(b.Page)
  fmt.Printf("page=%v, cur url is %v\n", i, url)
  client := &http.Client{}
  req, err := http.NewRequest("GET", url, nil)
  req.Header.Add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36")
  res, err := client.Get(url)
  if err != nil {
   log.Fatal(err)
  }
  defer res.Body.Close()
  if res.StatusCode != 200 {
   log.Fatalf("status code error: %d %s", res.StatusCode, res.Status)
  }
  body, _ := ioutil.ReadAll(res.Body)
  rsp := SearchRsp{}
  // todo
    b.Page++
 }
}

我们通过goquery能拿到body,此时是[]byte,我们需要转json格式,可以利用下面网站,将json数据粘贴过去,便可以生成对应的结构体:

https://mholt.github.io/json-to-go/

然后对里面的字段进行简化即可。这里把里面的Result从匿名结构体数组变为正常的,主要是方便append操作。

type SearchRsp struct {
 Code    int    `json:"code"`
 Message string `json:"message"`
 Data    struct {
  Seid     string   `json:"seid"`
  Page     int      `json:"page"`
  Pagesize int      `json:"pagesize"`
  NumPages int      `json:"numPages"`
  Result   []Header `json:"result"`
 } `json:"data"`
}

type Header struct {
 Author      string `json:"author"`
 Arcurl      string `json:"arcurl"`
 Title       string `json:"title"`
 Description string `json:"description"`
 Play        int    `json:"play"`
 Tag         string `json:"tag"`
}

到这里我们便可以进行Unmarshal,在上述todo代码处添加:

rsp := SearchRsp{}
_ = json.Unmarshal(body, &rsp)
allRsp = append(allRsp, rsp.Data.Result...)
if i == b.Page {
  numPages = rsp.Data.NumPages
}

这样最终的数据都变成了结构体的对应字段,方便进行后续操作。

3.excelize

有了上述数据之后我们要做的是对上述数据进行导出,这里采用excelize库,安装如下:

go get github.com/360EntSecGroup-Skylar/excelize

使用也比较简单,就是创建sheet,在对应sheet一行行数据插入即可。

上述第二节获取的数据是个结构体数组,而一行行插入的时候参数事切片,所以我们需要将结构体转切片。

这里给出转换方法:

func (b BilCrawl) StrctToSlice(r interface{}) []string {
 v := reflect.ValueOf(r)
 ss := make([]string, v.NumField())
 for i := range ss {
  ss[i] = fmt.Sprintf("%v", v.Field(i))
 }
 return ss
}

最后,便是写入了:首先写入A1写入头,随后在每行写入一行切片数据即可。

func (b BilCrawl) ExportExcel(res []Header) bool {
 f := excelize.NewFile()
 if b.Keyword == "" {
  return false
 }
 // 创建一个工作表
 index := f.NewSheet("Sheet1")
 var row_lines = len(res)
 // 第一次设置头
 r := []string{"作者", "视频地址", "标题", "描述", "播放量", "标签"}
 f.SetSheetRow("Sheet1", "A1", &r)
 for i := 0; i < row_lines; i++ {
  axis := "A" + strconv.Itoa(i+2)
  row := b.StrctToSlice(res[i])
  f.SetSheetRow("Sheet1", axis, &row)
 }
 // 设置工作簿的默认工作表
 f.SetActiveSheet(index)
 fmt.Println("save.....")
 // 根据指定路径保存文件
 if err := f.SaveAs("./bilibili.xlsx"); err != nil {
  fmt.Println(err)
 }
 return true
}

在上述代码中使用的接口与结构体,这里放出来如下:

type Crawler interface {
 DoCrawler()
 StrctToSlice(r interface{}) []string
 ExportExcel(rsp SearchRsp) bool
}

type BilCrawl struct {
 Url     string
 Keyword string
 Page    int
}

调用的时候如下:

b := bilibili.BilCrawl{"https://api.bilibili.com/x/web-interface/search/type?search_type=video", "java", 1}
b.DoCrawler()

这样就非常方便了,传递关键字,想要拿到的页数,就可以获取最后的结果了,嘿嘿。

本节完~

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-07-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 光城 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Let's Go!你输入关键字,我给你b站视频表!
    • 0.导语
      • 1.分析
        • 2.goquery
          • 3.excelize
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档