基于golang的爬虫demo,爬取微博用户的粉丝和关注者信息

9 篇文章 0 订阅
6 篇文章 0 订阅

基于golang的爬虫demo,爬取微博用户的粉丝和关注者信息

注意:仅供学习交流,任何非法使用与作者无关!

目录

基于golang的爬虫demo,爬取微博用户的粉丝和关注者信息

一、背景与取材

二、找规律

三、定位HTML的元素

四、设计过程

五、上代码

六、如何获取cookie

七、使用效果


一、背景与取材

现在大多数的爬虫程序都是基于python语言编写的,python具有相对完善的网络库,使用起来通俗易懂,特别适合小白入门。而且实现起来的效果也不错,也是爬虫界的实力担当。

博主选择了golang来编写,主要是选取golang支持原生并发,更轻量级的go协程更适合爬虫等高并发的程序。而且各个协程可以通过channel进行数据传输,极大地提高了爬取数据的效率,而这也是众多大厂作为服务器、云服务器开发的后后台编程语言。

好了,不再多说,上代码!

二、找规律

近年来微博为了防止数据被爬取,设置了很多的限制,但是新版本总是要对旧版本兼容那个,所以为了方便起见,使用老版本的API抓取。如下图

点击粉丝跳转到粉丝列表界面。如图

看到一页只能获取10条粉丝数据,然后进行翻页操作,查看翻页是否存在统一的规律。

此时,已经找到规律,页数根据请求的url里的page参数决定,而每页的最大数量是默认不可改变的。

如此可以拼接page参数,进行循环遍历获取每页的数据。

// 主要遍历页数伪代码如下
i = 1, max = 100;
who = 1642634100;

for i=1; i<max; i++{
    url = "https://weibo.cn/" + who + "/fans?page=" + i;
    r = RequestUrl(url);
    res = append(res , r)
}

三、定位HTML的元素

因为要获取粉丝或关注的信息,所以使用网页的审查元素进行元素的定位。

找到后发现信息放在table中,找到第一个是头像,最外面是A标签的头像,可以匹配到用户id,然后下面是用户昵称,下面是粉丝数量。

如此提取对应的匹配元素,前期工作就顺利完成。接下来进入设计、编码阶段。

四、设计过程


1.找到的网页分页规律
https://weibo.cn/1642634100/follow?page=1
https://weibo.cn/1642634100/follow?page=2
找到总页数
<input type="submit" value="跳页" />&nbsp;1/20页

2.匹配获取到每个关注者、粉丝
<td valign="top" style="width: 52px"><a href="https://weibo.cn/u/7086871638"><img src="https://tvax1.sinaimg.cn/crop.34.0.201.201.50/007JBN3gly8g8la7ql3xaj306k08daa3.jpg?KID=imgbed,tva&amp;Expires=1573966669&amp;ssig=9MQ8F40iE1" alt="pic" /></a></td>
<td valign="top"><a href="https://weibo.cn/u/7086871638">情感读心</a><br />粉丝13216人<br /><a href="https://weibo.cn/attention/add?uid=7086871638&amp;rl=1&amp;st=dcdea8">关注她</a></td>

3.将抓取到的信息写入文件

五、上代码

注意:抓取信息的前提是有认证信息的,就是要把自己的cookie放进去。微博做了权限,不允许未授权获取用户信息。如下代码中要换成自己的cookie。

package main

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"regexp"
	"strconv"
	"strings"
)

type UserInfo struct {
	UserId    string
	UserName  string
	Gender    string
	FansCount string
	IsFollow  string
}

func WriteFile(result, uid, title, fans, path string) {
	filename := path + "\\" + title + "_" + uid + "_" + fans + ".txt"
	f, err := os.Create(filename)
	if err != nil {
		fmt.Printf("os.Create err = ", err)
	}
	f.Write([]byte(result))
	f.Close()
}

func GetPageClient(url string) (result string, err error) {
	//伪装成浏览器客户端
	client := &http.Client{}
	req, err1 := http.NewRequest("GET", url, nil)
	if err1 != nil {
		err = err1
		return
	}
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36")
	req.Header.Set("cookie", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
	resp, err2 := client.Do(req)
	if err2 != nil {
		err = err2
		return
	}
	defer resp.Body.Close()

	for {
		buf := make([]byte, 1024*4)
		n, err := resp.Body.Read(buf)
		if n == 0 {
			break
		}
		if err != nil && err != io.EOF {
			fmt.Println("resp.Body.Read err = ", err)
			break
		}
		result += string(buf[:n])
	}

	return
}

func GetWork(uid, fans, path string) {
	pageEnd := 1
	title := "123"
	url1 := "https://weibo.cn/" + uid + "/" + fans + "?page=1"
	//fmt.Printf("第%d页%s的url = %s...\n", 1, fans, url1)
	result, err := GetPageClient(url1)
	if err != nil {
		fmt.Println("GetPageClient err", err)
	}
	//匹配页数
	rePage := regexp.MustCompile(`<input type="submit" value="跳页" />&nbsp;1/(?s:(.*?))页`)
	if rePage == nil {
		fmt.Println("regexp.MustCompile err")
	}
	pageCount := rePage.FindAllStringSubmatch(result, 1)
	for _, data := range pageCount {
		pageEnd, _ = strconv.Atoi(data[1])
	}
	//匹配title
	reTitle := regexp.MustCompile(`<title>(.*)关注的人</title>`)
	if reTitle == nil {
		fmt.Println("regexp.MustCompile err")
	}
	titles := reTitle.FindAllStringSubmatch(result, 1)
	for _, datas := range titles {
		title = datas[1]
	}

	var results string
	for i := 1; i <= pageEnd; i++ {
		url := "https://weibo.cn/" + uid + "/" + fans + "?page=" + strconv.Itoa(i)
		//fmt.Printf("第%d页%s的url = %s...\n", i, fans, url)
		result, err := GetPageClient(url)
		if err != nil {
			fmt.Println("GetPageClient err", err)
		}

		//匹配结果
		reUser := regexp.MustCompile(`<td valign="top"><a href="https://weibo.cn/u/(?s:(.*?))">(?s:(.*?))</a>(?s:(.*?))丝(?s:(.*?))人<br/>(?s:(.*?))</td>`)
		if reUser == nil {
			fmt.Println("regexp.MustCompile err")
		}
		var tmp UserInfo
		userInfo := reUser.FindAllStringSubmatch(result, -1)
		for _, data := range userInfo {
			tmp.UserId = data[1]
			tmp.UserName = data[2]
			tmp.FansCount = data[4]
			tmp.IsFollow = "false"
			if strings.Contains(data[5], "已关注") {
				tmp.Gender = "未知"
				tmp.IsFollow = "true"
			} else if strings.Contains(data[5], "他") {
				tmp.Gender = "男"
			} else if strings.Contains(data[5], "她") {
				tmp.Gender = "女"
			}
			tmps := "{ UserId:" + tmp.UserId + " , UserName:" + tmp.UserName + " , FansCount:" + tmp.FansCount + " , Gender:" + tmp.Gender + " , IsFollow:" + tmp.IsFollow + " }\n"
			results = results + tmps
			fmt.Printf("爬取的信息:%+v\n", tmp)
		}
	}
	WriteFile(results, uid, title, fans, path)
}

func main() {
	var uid, fans, path, yes string
	for {
		fmt.Println("输入微博账号")
		fmt.Scan(&uid)
		fmt.Println("输入爬取关注者、粉丝(如fans、follow)")
		fmt.Scan(&fans)
		fmt.Println(`请输入保存路径(如C:\Users\Desktop)`)
		fmt.Scan(&path)

		GetWork(uid, fans, path)

		fmt.Println("爬取完成,是否继续爬取?Y/N")
		fmt.Scan(&yes)

		if yes == "N" || yes == "n" {
			break
		}
	}

}

六、如何获取cookie

打开浏览器,进入微博登录界面,输入正确的用户名密码。实现正常登陆操作获取cookie。

使用浏览器网络分析,拿到请求中的cookie。如下图

七、使用效果

注意:仅供学习交流,任何非法使用与作者无关!

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

byzf

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值