网页抓取qq(授人以鱼授人以渔爬虫爬虫教程教程 )
优采云 发布时间: 2022-04-03 19:08网页抓取qq(授人以鱼授人以渔爬虫爬虫教程教程
)
授人以鱼不如授人以渔
爬虫教程上千种,总觉得市面上的教程很少能讲到精髓。
本期我会做一个本地扫码登录获取session的爬虫。
开始战斗准备
我们的目标是能够在本地执行QQ音乐的二维码扫描登录。
即把登录二维码保存到本地,弹出二维码,如果登录成功,删除二维码,保留登录信息。
我们先写显示二维码函数,删除二维码函数,保存二维码函数。
编写代码
import sysimport os import subprocess'''用于在不同OS显示验证码'''def showImage(img_path): try: if sys.platform.find('darwin') >= 0: subprocess.call(['open', img_path]) elif sys.platform.find('linux') >= 0: subprocess.call(['xdg-open', img_path]) else: os.startfile(img_path) except: from PIL import Image img = Image.open(img_path) img.show() img.close()<br />'''验证码验证完毕后关闭验证码并移除'''def removeImage(img_path): if sys.platform.find('darwin') >= 0: os.system("osascript -e 'quit app \"Preview\"'") os.remove(img_path)<br />'''保存验证码图像'''def saveImage(img, img_path): if os.path.isfile(img_path): os.remove(img_path) fp = open(img_path, 'wb') fp.write(img) fp.close()
获取二维码下载链接
进入后打开F12开发者工具,点击登录按钮,打开登录框。
我们首先获取我们的图片信息,点击Img选项并下拉找到二维码的网页链接。
单击标题以查看获取此图像所需的链接:
看一下二维码网站需要的参数:
为了保证每次使用的正确性,我们多次刷新查看。
我们发现变化的参数只是at参数,研究考察了t参数是否可以正常访问。
打开postman工具,新建requests查询,输入url和params,发现二维码正常获取。
那么我们暂时认为t参数不是加密参数,我们引入一个0到1之间的随机数。
t 参数将 Python 语法转换为 random.random()
编写代码
## 伪代码self.cur_path = os.getcwd()params = { 'appid': '716027609', 'e': '2', 'l': 'M', 's': '3', 'd': '72', 'v': '4', 't': str(random.random()), 'daid': '383', 'pt_3rd_aid': '100497308',}response = self.session.get(self.ptqrshow_url, params=params)saveImage(response.content, os.path.join(self.cur_path, 'qrcode.jpg'))showImage(os.path.join(self.cur_path, 'qrcode.jpg'))
登录抓包
为了防止数据包过多,我们将捕获的数据包清除,然后点击返回ALL界面。
点击登录跳转,但是这时候我们需要检查数据包的状态,因为你登录后会出现302跳转的现象。如果没有终止抓包,则跳转后数据包将被清空。
我们首先要了解红色标注的两个按钮的作用
继续多次访问,发现ptqrtoken、action、login_sig都是变量。
根据以16开头的字符串的可变长度,盲目猜测动作变量的第三位是时间戳的倍数。
随意在变量参数中打开一个timestamp() URL,发现它扩展了一千倍。
动作变量在 Python 中写为 'action': '0-0-%s' % int(time.time() * 1000)
棘手的变量加密参数第一个参数
我们正常打开开发者窗口,准备找到加密参数的位置。
点击Initiator拨盘,在这里我们可以找到每个参数的来源,直接点击进入第一个loadScript。
我们发现我们得到了一串未格式化的 Javascript 代码。
随便开个在线format()网站,格式化完所有代码后,在线查看加密参数,看看这里经历了什么加密。
params.ptqrtoken=$.str.hash33($.cookie.get("qrsig"))pt.ptui.login_sig=pt.ptui.login_sig||$.cookie.get("pt_login_sig");
我们获得了这两个加密参数的来源,似乎与cookies的加密有关。
现在我们已经找到了加密的位置,让我们开始寻找 cookie。
这两个参数可能出现的地方并不多,我们也不需要看到每一个返回的结果。
重新刷新后,找到弹出登录框的返回信息。
是一个 GET 请求,URL 是
参数是:
为了保险起见,多次刷新,看看是否有额外的加密参数。
好在好在都是正常的死参数,好直接访问。
编写代码
session = requests.Session()params = { 'appid': '716027609', 'daid': '383', 'style': '33', 'login_text': '授权并登录', 'hide_title_bar': '1', 'hide_border': '1', 'target': 'self', 's_url': 'https://graph.qq.com/oauth2.0/login_jump', 'pt_3rd_aid': '100497308', 'pt_feedback_link': 'https://support.qq.com/products/77942?customInfo=.appid100497308',}response = session.get('https://xui.ptlogin2.qq.com/cgi-bin/xlogin?', params=params)cookie = session.cookiesprint(cookie)### 为了好看在这里我给全都拆开看了。# -> , # -> , # -> , # -> , # -> , # -> ]>
运行后,我们找到了pt_login_sig参数,直接从字典中得到了名为variable的参数并保存。
第二个参数1.得到
由于第一个参数在登录框中,所以第二个参数的盲猜应该保存在二维码中。
我刚刚得到了二维码的代码。事不宜迟,拿起饼干
编写代码
session = requests.Session()params = { 'appid': '716027609', 'e': '2', 'l': 'M', 's': '3', 'd': '72', 'v': '4', 't': str(random.random()), 'daid': '383', 'pt_3rd_aid': '100497308',}response = session.get('https://ssl.ptlogin2.qq.com/ptqrshow?', params=params)cookie = session.cookiesprint(cookie)# -> ]>
就一个真的很好,正是我们想要的qrsig,用字典get来提取key的值信息,就这么简单搞定。
第二个参数hash33加密
我们得到的加密参数不是可以直接输入代码的东西,我们要得到hash33加密的东西。
单击搜索后,搜索 hash33 查询。只有一个信息点可以进去查找代码。
hash33加密算法的Javascript版本:
<p>hash33: function hash33(str) { var hash = 0; for (var i = 0, length = str.length; i