入门客AI创业平台(我带你入门,你带我飞行)
博文笔记

CSDN批量关注 python+golang+selenium

创建时间:2018-10-19 投稿人: 浏览次数:297

 

最近研究了下selenium,除了模拟鼠标点击,或者input操作外,还发现了个非常神奇的地方,可以执行JS代码。

这简直就像发现新大陆一样!如果能够这样的话,根本不用去考虑什么cookie,加密,认证等等!

于是想做下实验,于是我想到了csdn。。。(希望不要被封账号),通过selenium批量关注好友~~·哈哈哈

1. 首先我们当然是开始分析CSDN关注的时候网络请求是什么

随便找一个陌生人的主页:

https://me.csdn.net/weixin_41792682 (缘分选择,哥们见谅)

打开debug窗口,查看点击“关注”后执行的代码:

 

格式之后,发现了如下代码。 

可以看出是通过ajax发送post请求,然后结合下network抓包的数据:

就能分析出来需要执行的简化版js代码如下:

$.ajax({
	contentType: "application/json",
  	cache: false, 
	async: false, 
	type: "POST",
	data:JSON.stringify({username: username}),
  	url: "https://me.csdn.net/api/relation/create",
	success: function (data, status) {
		console(data);
	}
});

 也就是如果需要关注某个用户,只需要将username传入data中就行了。那如何批量获得用户名呢?

2. 爬取用户名

csdn的用户名命名规则不统一,有些是昵称,有些是微信号,或者qq

 比如:

https://me.csdn.net/weixin_42219106
https://me.csdn.net/qq_41893578

并不是id递增这么简单。最后发现,每个人的主页都会展示粉丝和关注,一共12个人。

查看网页源码:

从a标签中能提取出。

接下来的做法就是,从一个用户的主页开始,抓取出关注和粉丝的地址,接下来对这些关注和粉丝的用户递归抓取。就能抓取出源源不断的用户主页。

这一段通过python实现:

import requests
import bs4
import time

def getUsernamesFromUrl(user):
    users=[]
    s = requests.Session()
    ret = s.get(user)
    soup = bs4.BeautifulSoup(ret.content, "html.parser")

    matches=soup.findAll(attrs={"class": "fans_title"})
    for match in matches:
        print(match["href"])
        users.append(match["href"])
    HistoryUsers.append(user)
    return users

if __name__ == "__main__":
    HistoryUsers=[]
    PendingUsers=[]
    startUser="https://me.csdn.net/dqcfkyqdxym3f8rb0"
    PendingUsers.append(startUser)
    count=0
    while True:
        time.sleep(1)
        if len(PendingUsers)>0:
            user=PendingUsers.pop()
            users=getUsernamesFromUrl(user)
            for u in users:
                if u not in HistoryUsers:
                    print("new user:",u)
                    count+=1
                    index=count//100
                    filename="csdn/csdn_users{}.txt".format(index)
                    with open(filename,"a+") as f:
                        f.writelines(u.split("/")[-1:].pop()+"
")
                    PendingUsers.append(u)
        else:
            time.sleep(1)

最终会在csdn文件夹中生成多个文件,每个文件中有100个username

 

 

有了用户名,有了需要执行的代码,接下来的事情,就是从文件读取用户名,然后依次去执行。

3. go+selenium模拟执行js

最后到了最激动人心的地方。selenium的webdriver python有支持的库,golang也有,个人感觉go用起来更爽,因为有天生的goroute

用到的库:

"github.com/tebeka/selenium"

具体用法可参考GitHub,这里就不介绍了,可以模拟按键在input中输入用户名密码,点击登录按钮。

我就自己手动登录,登录成功后,按下回车,让程序往下跑:

func main() {
    //自己封装了下selenium,只是为了方便使用,没有实质修改
	wd, err := webApi.NewWeb("firefox", port)
	if err != nil {
		panic(err)
	}
	defer func() {
		wd.Close()
	}()
    //打开登录页面
	wd.Open("https://passport.csdn.net/account/login")
	var url string
	fmt.Println("手动登录")
    //程序跑到这里会等待我输入,利用这个时间,我可以去手动登录
	fmt.Scanln(&url)
	wd.Open("https://me.csdn.net/weixin_43446306")
	wd.GetDriver().SetImplicitWaitTimeout(time.Second * 5)
    //两个goroute,1个去读usernames,另一个去执行js
	go readNamesFromFile(filename)
	go fetchUserNames(wd)
    
    ...
}

读取用户名:

func readNamesFromFile(file string) {
	f, err := os.Open(file)
	if err != nil {
		log.Debug("err:$v", err)
		return
	}
	buf := bufio.NewReader(f)
	for {
		timer := time.NewTicker(time.Second * 2)
		<-timer.C
		line, err := buf.ReadString("
")
		line = strings.TrimSpace(line)
		log.Debug("got name %s", line)
		usernamesChan <- line
		if err != nil {
			if err == io.EOF {
				log.Debug("end of file")
				return
			}
			return
		}
	}
	return
}

func fetchUserNames(wd *webApi.WebDriver) {
	for {
		username := <-usernamesChan
		script := fmt.Sprintf(`function test(){
	var ret="nok"; $.ajax({
	contentType: "application/json",
  	cache: false, 
	async: false, 
	type: "POST",
	data:JSON.stringify({username:"` + username + `"}),
  	url: "https://me.csdn.net/api/relation/create",
	success: function (data, status) {
		ret= "ok";
	}
	}); return ret}
	return ( test());
	`)

		ret, _ := wd.GetDriver().ExecuteScript(script, nil);
		if reflect.TypeOf(ret) != reflect.TypeOf("ok") {
			return
		}
		if ret.(string) == "ok" {
			beelog.Debug("follow user %s ok", username)
		}
	}

}

最终效果,在浏览器网络窗口能看到:

这种事情当然要开小号。

声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。
  • 上一篇:没有了
  • 下一篇:没有了
未上传头像