Python爬虫-Weibo模拟登录及crawling

2023-11-10 05:50

本文主要是介绍Python爬虫-Weibo模拟登录及crawling,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近在学习python爬虫,并尝试用在微博上。然而时代在变化,网上的资料已经过时,基本上都无法在2021年使用,因此通过参考资料和自己钻研,最终走通了crawling过程。下面我会详细说明整个流程及注意事项,一方面是总结,一方面也为大家提供一个参考,希望能够帮助到大家。

python版本3.9.2

需要一个可以正常使用的Weibo账号及密码。

需要一部能够正常使用的手机用于验证。

可选网页记录工具,我这里使用的是Fiddler,大家也可以使用其他的工具,有助于理解原理。

注意我这里是模拟网页端,和手机端是不一样的。但其实网页端是最难的。

----------------------------------------------------

目录

 Python模拟微博登录

微博预登录

微博登录

短信验证

私信验证

评论爬取

后记


 Python模拟微博登录

相信小伙伴们在使用网页端浏览微博的时候会发现,如果要登录网页版,除了用户名密码外,微博现在必须进行身份验证!如下图。

验证方式有三种:短信验证私信验证扫码验证。无论哪种验证方式,都需要手机端进行!所以如果要使用Python模拟登录微博,首次必须借助手机进行验证!有的小伙伴看到这儿可能不高兴了:这不坑爹吗,难道每次爬取数据都要用手机验证下,这也太麻烦了!先别急,一旦通过了第一次验证,我们就能够获取登录Cookie信息,只要把Cookie保存在本地,那么在接下来很长一段时间都可以通过直接读取Cookie进行数据爬取,无需再次手机端验证!其实第一次的手机端验证就是为了获取这个Cookie。这里的三种验证方式我们只选择短信验证私信验证。扫码验证比较麻烦(其实是博主太懒没有研究),不过原理都是差不多的。

那么重点来了:怎么获取这个Cookie?

获取cookie的过程是比较麻烦的,我会尽量讲清楚。

微博预登录

在登录微博之前,我们需要先进行预登录,不要问为啥,微博就是这样设计的😶。

首先,网页端微博的登录地址在此新浪通行证登录。

这里我们可以把Fiddler打开,看看登录的整个过程发起了哪些请求。这里选择短信登录(注意,微博限制了用户每天短信验证码的使用次数,一天内最多接收10次左右的验证码,所以还是更推荐大家使用私信验证,因为私信验证不限制次数)。Fiddler会显示非常多的请求信息。我们可以使用Host过滤出我们需要分析的请求,如下图。

我们需要的就是使用Python模拟发送这些请求,最终获得Cookie数据。

上图中第一个请求prelogin就是预登录请求,用于获取公钥及其他验证信息。这里相当于是Weibo的第一层防护

我们详细看下这个请求:

请求头如下图。请求头中唯一需要注意的是Referer参数。在使用Python模拟该请求时,请一定加上Referer,不然无法正常发送请求

再看下请求的params:

entry、callback、rsakt、client都是固定,_则是当前的毫秒级时间戳。su是base64加密后的用户名,加密方法如下:

def get_su(self):username_quote = quote_plus(self.username)username_base64 = base64.b64encode(username_quote.encode("utf-8"))return username_base64.decode("utf-8")

接下来看下返回body。这里我们把返回的json串格式化仔细看下:

retcode表示返回状态,0表示返回成功。servertime依旧是时间戳,pcid不需要,跳过。nonce为随机数。pubkey为公钥,rsakv是下一步请求中需要使用到的字符串。

返回的这些信息中我们需要使用到的是nonceservertimersakvpubkey,这些信息都是下一步登录请求中需要使用到的参数其中nonce、servertime和pubkey是用来对密码sp进行加密的。加密代码如下:

def get_password(self, pubkey, servertime, nonce):string = (str(servertime) + "\t" + str(nonce) + "\n" + str(self.password)).encode("utf-8")public_key = rsa.PublicKey(int(pubkey, 16), int("10001", 16))password = rsa.encrypt(string, public_key)password = binascii.b2a_hex(password)return password.decode()

通过预登录,我们其实只是获得了登录请求的前置参数,接下来才是真正的登录请求。

微博登录

接下来需要做下准备发起登录Post请求,请求的body信息如下图。其中su和sp即我们加密后的用户名和密码,加密方法参见上一节的get_su和get_password方法。servertime、nonce、rsakv均是prelogin预登录返回的数据。其他则是固定值。

post_data={'entry': 'sso',                          'gateway': '1',                           'from': '',                               'savestate': 30,                          'useticket': 0,                           'pagerefer': 'http://login.sina.com.cn/', 'vsnf': 1,                                'su': su,                  //加密后的用户信息'service': 'sso',                         'servertime': servertime,  //prelogin请求中返回'nonce': nonce,            //prelogin请求中返回'pwencode': 'rsa2',                       'rsakv': rsakv,            //prelogin请求中返回'sp': sp,                  //加密后的密码信息'sr': '1920*1080', 'encoding': 'UTF-8', 'cdult': 3, 'domain': 'sina.com.cn', 'prelt': 25, 'returntype': 'TEXT' }

请求params中client为固定值,_为毫秒级时间戳。

看下header,注意红框中的参数记得带上。

如果数据没问题,发起登录请求后返回值如下图。可以看到,虽然我们正确发送了登录请求(用户名密码都正确),微博网页端依旧要求我们进一步进行验证,这里算是Weibo的第二层防护

返回结果中重要的信息是'protection_url'中的token值,我们需要手动提取出该值,后面会用到。

下面进行下一步验证。验证分三种:1、短信验证码验证,2、私信验证,3、扫码验证。下面仅介绍短信验证码验证和私信验证。

短信验证

首先我们要模拟微博网页端向我们的手机发送短信验证码,这里的难点是如何获取用户手机号。有的小伙伴要问了,我当然晓得我记姬的手机号,还用获取❓没错,因为接下来的请求使用的手机号都是加了密的,即便你知道自己的手机号,也不能直接使用。我们其实并不需要知道如何加密,而只需要知道加密后的手机号即可!

那么下面就是一个简单的到页面上爬取手机号(已加密)的操作。请求如下图。注意请求params,callback_url是固定值,而token则是上一步登录时我们获取到的token。

再看下请求返回的页面(下图),红框中即加密后的手机号,也就是我们需要的字符串。

 我们可以使用BS爬取。

# 发送get请求,并解析结果,获得加密后的电话号码protection_url = 'https://login.sina.com.cn/protection/index?callback_url=http://login.sina.com.cn/&token=' + tokenprotection_url_res = self.session.get(protection_url).textprotection_url_res_bs = BeautifulSoup(protection_url_res, 'html.parser')encrypt_mobile = protection_url_res_bs.find(id='ss0').get('value')

到这里我们就获取到了加密后的手机号,接下来发送短信,请求如下。请求params依旧会传token,body里放入加密后的手机号。

headers如下,注意红框中的信息要填上。其中Referer是一个地址,其中用到了token和callback_url两个参数。

相关代码如下:

# 构造发送短信的请求send_message_url = 'https://login.sina.com.cn/protection/mobile/sendcode?token=' + tokenreferer = "https://login.sina.com.cn/protection/index?token={}&callback_url=http%3A%2F%2Flogin.sina.com.cn%2F".format(token)headers = {'Referer': referer,'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8"}body = {'encrypt_mobile': encrypt_mobile}data = urllib.parse.urlencode(body)# 发送验证码到手机res = self.session.post(send_message_url, headers = headers, data = data)

如果短信发送成功,那么我们应该会收到一条短信验证码。之后需要手动将验证码输入Python input中用于验证,我们可以简单的用message_code = input('输入短信验证码')等待用户输入验证码。注意验证码时效性为10分钟,10分钟内收到的都会是同一个验证码。

收到验证码后,终于能够真正开始短信验证了,请求如下图。请求Params中仍旧需要放入token。Body里面包括加密后的手机号和收到的短信验证码。如果请求成功,会返回一个json字符串。

相关代码如下。注意这里的headers依旧使用的是上一步的headers,这里就不展示了。

login_url = 'https://login.sina.com.cn/protection/mobile/confirm?token=' + token
login_post_data = { 'encrypt_mobile': encrypt_mobile, 'code': message_code}
login_post_res = self.session.post(login_url, headers = headers, data = login_post_data)

我们看下返回的json字符串。retcode为20000000且msg为succ说明请求成功。到这儿可能有的小伙伴已经不耐烦了,怎么发送了这么多请求还没有看到cookie的影子??别急,就差一步啦。注意到返回的json串中的data有一个'redirect_url'属性

我们提取出redirect_url,然后直接发起一个get请求,如下图。该请求不需要添加任何参数,直接get就行。我们可以在Response中看到返回了6个Cookie。其中的SUB就是我们需要的Cookie。到这儿我们终于成功获取到Cookie啦。

这里需要额外提醒下,我的全流程都走的网页端微博,如果大家想从手机端爬取数据,这里的Cookie是不共用的!本人尝试过拿着这里网页端获取的Cookie到手机端网页地址爬取数据,怎么都无法成功,所以建议大家先想好是从哪个地方爬取数据。

接下来我们需要使用python的cookiejar工具单独提取出Cookie中SUB的键值,并以字符串的形式保存在本地文件中。有些小伙伴可能会问,都已经获得了完整的Cookie对象了,干嘛不直接使用,为什么非要再单独提取出来SUB?因为返回的Cookie对象中的Domain和我们接下来将要爬取的页面的Domain不一样!因此是无法直接使用的!所以我们需要单独提取出SUB。

保存Cookie的代码如下,我们只需要SUB和它的Value。

def save_cookies_lwp(cookiejar, filename):lwp_cookiejar = http.cookiejar.LWPCookieJar()if not os.path.exists(filename):file = open(filename,'w')# file.write('#LWP-Cookies-2.0')file.close()# 寻找cookie中的SUBfor c in cookiejar:args = dict(vars(c).items())args['rest'] = args['_rest']del args['_rest']c = http.cookiejar.Cookie(**args)if c.name=='SUB':SUB = c.valuefile = open(filename, 'w')file.truncate()file.write(SUB)file.close()print('cookie已经保存在本地!值为:' + SUB)

到这里我们的Cookie已经获取并保存到本地了,在之后的数据爬取中,我们只要在请求中手动设置Cookie即可,如下。可以看到评论数据的域名为’weibo.com',和Cookie获取时的‘sina.com.cn’是不一样的哦。

def getPage(self, url):# 爬取数据之前先尝试使用cookieSUB = load_cookies_from_lwp(self.cookie_file)headers = {'Host': 'weibo.com', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'}self.session.cookies['SUB'] = SUBhtml = self.session.get(url, headers=headers)return html

私信验证

私信验证的过程与短信验证差不多,甚至还要更简单些,因为不再需要手动爬取加密的手机号。发送私信请求如下图。

若发送成功,我们会在手机上的微博app里收到一条登录提示消息,只要点击允许即可。

这里和短信验证不同的是,私信验证纯粹走的是手机端,不需要我们在程序里单独发送请求,因此程序中需要持续监测验证状态,不然无法知道什么时候验证成功。我这里是尝试获取10次状态,每次休息2秒钟,大家可以根据需要修改。

stop = False
getStatus_url = 'https://login.sina.com.cn/protection/privatemsg/getstatus'
body = {'token': token}
data = urllib.parse.urlencode(body)
count = 0 # 尝试10次
while (not stop):time.sleep(2) # 每2秒请求一次html = requests.post(getStatus_url, data=data, headers=headers)ret_json = json.loads(html.text)redirect_url = ret_json.get('data').get('redirect_url')count += 1if (redirect_url != '' or count>10):stop = True
if (redirect_url == ''):print('未能在时间内正确发送私信验证!登陆失败!')return

如果成功进行了私信验证,则返回的信息中又会出现'redirect_url'。接下来的步骤和短信验证是一样的,这里不赘述了。

好了,到这里我们终于完成了第一步(是的,才第一步):Python模拟微博登录,下面就开始搞事情拉。

评论爬取

难点在于,微博使用的“懒加载”,即并不会一次性的展示尽可能多的数据,而需要用户主动操作去获取,如用户滑鼠标或点击“加载更多”。

我们这里以最近大火的利老师为例做说明:

我们打开他置顶的这条“下班”微博,打开Fiddler的跟踪功能,然后尝试加载几次他的微博评论,经过观察,可以看到是以下这些接口在获取数据。评论数据就藏在返回的data中的html里。

我们首先仔细看下第一个请求。其中ajwvr和from都是固定值。id指向的就是本条微博,后续的查询也不会变,__rnd是毫秒级时间戳。注意Headers中加上Host参数。Cookie中放入咱们的SUB即可。

观察下第一页数据的返回值。这里我将html格式化了,方便大家查看。红框中的数据是下一页数据的信息。也就是说我们必须先爬取前页数据才能获取到下一页数据的入参......注意这里的action-data是放在html最后的div中,node-type为“comment_loading”。

那么我们继续看下第二页数据。

可以看到和第一页数据的格式是一样的。那么这就可以开始愉快的爬数据了吧?不行呢。我们再继续看下第三页的数据。可以看到下一页的请求参数数据又跑到了html最后一个a标签中......这算是第三层防护,不过不用担心,因为接下来的数据都是这种格式。这里就是想要提醒大家,如果使用微博网页端进行数据爬取,需要考虑到这两种情况。

后记

如果你能看到这里,首先感谢你这么有耐心,也希望你成功。其实笔者并不是爬虫专家,甚至python都是现学现卖的。不过通过这次“实验”,让我感到爬虫的难度还是蛮高的。难点不都是来自于技术,更多的是来自于和网站开发者的博弈。网站的开发者为了防止爬虫一定会设置重重阻碍。而我们要做的就是仔细观察,水来土掩,见招拆招,突破重重阻拦,这就需要开发者具备极大的耐心和分析能力。只能说这个过程是艰辛也是有趣的。

github链接在此https://github.com/Lisz112/Python-/blob/main/PythonScrawlerWeibo.py

这篇关于Python爬虫-Weibo模拟登录及crawling的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/380742

相关文章

Security OAuth2 单点登录流程

单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自独立的软件系统,提供访问控制的属性。当拥有这项属性时,当用户登录时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以轻型目录访问协议(LDAP)来实现,在服务器上会将用户信息存储到LDAP数据库中。相同的,单一注销(single sign-off)就是指

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

【C++】_list常用方法解析及模拟实现

相信自己的力量,只要对自己始终保持信心,尽自己最大努力去完成任何事,就算事情最终结果是失败了,努力了也不留遗憾。💓💓💓 目录   ✨说在前面 🍋知识点一:什么是list? •🌰1.list的定义 •🌰2.list的基本特性 •🌰3.常用接口介绍 🍋知识点二:list常用接口 •🌰1.默认成员函数 🔥构造函数(⭐) 🔥析构函数 •🌰2.list对象

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

usaco 1.2 Transformations(模拟)

我的做法就是一个一个情况枚举出来 注意计算公式: ( 变换后的矩阵记为C) 顺时针旋转90°:C[i] [j]=A[n-j-1] [i] (旋转180°和270° 可以多转几个九十度来推) 对称:C[i] [n-j-1]=A[i] [j] 代码有点长 。。。 /*ID: who jayLANG: C++TASK: transform*/#include<

【测试】输入正确用户名和密码,点击登录没有响应的可能性原因

目录 一、前端问题 1. 界面交互问题 2. 输入数据校验问题 二、网络问题 1. 网络连接中断 2. 代理设置问题 三、后端问题 1. 服务器故障 2. 数据库问题 3. 权限问题: 四、其他问题 1. 缓存问题 2. 第三方服务问题 3. 配置问题 一、前端问题 1. 界面交互问题 登录按钮的点击事件未正确绑定,导致点击后无法触发登录操作。 页面可能存在

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

nudepy,一个有趣的 Python 库!

更多资料获取 📚 个人网站:ipengtao.com 大家好,今天为大家分享一个有趣的 Python 库 - nudepy。 Github地址:https://github.com/hhatto/nude.py 在图像处理和计算机视觉应用中,检测图像中的不适当内容(例如裸露图像)是一个重要的任务。nudepy 是一个基于 Python 的库,专门用于检测图像中的不适当内容。该

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip