爬虫day01(上午) 模拟登录古诗文网

前言:今天是学习爬虫的第一天,因为看的教学视频比较老,所以很多案例都不能用了,于是我自己发挥动手操作,做了个比视频里更有含金量的练习,由于与视频案例大有不同,所以期间发生了点问题,经过探索现已解决,留此纪录。

前面是我一开始犯的错误,最后附上完整代码。

下面是我一开始的操作:

首先我访问古诗文网的登陆页面

登录古诗文网 (gushiwen.cn)https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx我从它的这个链接就可以看出了估计就是https://so.gushiwen.cn/user/login.aspx这个页面去登录,登录后发生跳转到个人页面。因此其实我用url=‘https://so.gushiwen.cn/user/login.aspx’或者等于上面完整的都是一样的。

一开始我当时用刚学的知识去request.get(略).text 然后xpath获得了验证码图片的地址,然后request.get(略).context 获得了验证码的tup信息并且保存到了本地里。然后通过识别验证码工具获得图片里的内容。最后发送post请求模拟登录一气呵成。

于是当我打开爬下来的页面得到了以下弹窗:

这可把我惊呆了,于是我print出最后一次post请求返回的response的url,发现还是登陆页面的url,状态码还是200。这与我手动登录然后进行浏览器抓包的结果可不一样。正常应该是post请求把账号密码给这个页面,然后302,然后301跳转到页面200.我的收藏_古诗文网 (gushiwen.cn)https://so.gushiwen.cn/user/collect.aspx

通过浏览器正常登录是这样的

蓝色的这三个分别对应 302->301->200

因为我显示’验证码‘错误的这个响应的状态码也是200,我就以为是跳转成功了,以为只是某步出现了问题。

经过探索,发现requests.get()等获得的页面如果发生跳转,最后返回的就算跳转后的页面,这就更加坚定了我以为跳转成功的信念。我得知加上

allow_redirects=False

就可以阻止它的跳转,那么我将会获得302的状态码

经过我尝试,返回的依然是200,我又惊了。

于是我转换思维,是不是登录失败了呢?当我恍然大悟时,突然觉得自己好蠢,它都告’验证码错误了‘肯定就算登陆失败了呀,这个200和返回的url依然是登陆页面明显是因为登陆失败了让我重新登录。。。麻了。。

经过我验证,验证码确实是准确无误的,那么问题出现在哪呢?我根据浏览器抓包工具分析了每个请求和响应,唯独没去看cookie,我心想这不会还得携带cookie才能登录吧。

于是我继续学习,学会了用session替换requests,我替换了第一次获取登陆页面,替换了第三次发送post请求模拟登录,还是不行,抱着试试的心态把第二次获取图片数据的requests也换了session,还真成了!!!

经过我仔细检查浏览器里的cookie,发现它这个发起请求时还真带着验证码对应的cookie!!!

即我浏览器访问这个页面的时候,他会自动加载验证码图片的同时给我浏览器返回一个验证码cookie,我登陆的时候要带着这个cookie才行!!

完整代码:

验证码识别模块:

我用的这个图片识别打码平台,因为视频里介绍的云打码已经无了。图片识别-打码平台-打码网站-识别验证码-图鉴网络科技有限公司 (kuaishibie.cn)

import base64
import json
import requests


# 一、图片文字类型(默认 3 数英混合):
# 1 : 纯数字
# 1001:纯数字2
# 2 : 纯英文
# 1002:纯英文2
# 3 : 数英混合
# 1003:数英混合2
#  4 : 闪动GIF
# 7 : 无感学习(独家)
# 11 : 计算题
# 1005:  快速计算题
# 16 : 汉字
# 32 : 通用文字识别(证件、单据)
# 66:  问答题
# 49 :recaptcha图片识别
# 二、图片旋转角度类型:
# 29 :  旋转类型
#
# 三、图片坐标点选类型:
# 19 :  1个坐标
# 20 :  3个坐标
# 21 :  3 ~ 5个坐标
# 22 :  5 ~ 8个坐标
# 27 :  1 ~ 4个坐标
# 48 : 轨迹类型
#
# 四、缺口识别
# 18 : 缺口识别(需要2张图 一张目标图一张缺口图)
# 33 : 单缺口识别(返回X轴坐标 只需要1张图)
# 五、拼图识别
# 53:拼图识别
def base64_api(uname, pwd, img, typeid):
    with open(img, 'rb') as f:
        base64_data = base64.b64encode(f.read())
        b64 = base64_data.decode()
    data = {"username": uname, "password": pwd, "typeid": typeid, "image": b64}
    result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)
    if result['success']:
        return result["data"]["result"]
    else:
        return result["message"]
    return ""

模拟登录.py

这里我没有删去测试用的print出来的cookie,可以用作对比每次都获得了什么。

import requests
from lxml import etree
from shibie import base64_api

# 登陆成功后经过分析没有直接返回页面 而是发生了重定向(302 Location) 不是json数据不用处理  经过分析获取url
# 使用session记录会话

session = requests.Session()
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.62'}

# 获取登陆页面
res1 = session.get(url='https://so.gushiwen.cn/user/login.aspx?',
                   headers=headers).text

# 从登陆页面中获取验证码图片
tree = etree.HTML(res1)
code_url = 'https://so.gushiwen.cn' + tree.xpath("//img[@id='imgCode']/@src")[0]
print('get请求访问页面后获得的cookie',session.cookies)
res2 = session.get(url=code_url, headers=headers).content

with open(f'code_photo/code.jpg', 'wb') as f:
    f.write(res2)
img_path = 'code_photo/code.jpg'
result = base64_api(uname='suiyv', pwd='你的密码', img=img_path, typeid=3)
print('拿到验证码后的cookie',session.cookies)

# 模拟登录
data1 = {
    '__VIEWSTATE': 'hs0mnwidq4m/uindCZbrLCG+ikW3f5709zeotv+IBQyCs2gUymA5JjRgb+X/flzsInVB0pt4mbjvjs30tTjjz55J6PTWEJBNk3jiTHeEhlTaixBRto8UBtFFH1M=',
    '__VIEWSTATEGENERATOR': 'C93BE1AE',
    'from': 'http://so.gushiwen.cn/user/collect.aspx',
    'email': '你的账号',
    'pwd': '你的密码',
    'code': result,
    'denglu': '登录',
}
# headers['Cookie'] = 'xxx'
response = session.post(
    url='https://so.gushiwen.cn/user/login.aspx',
    headers=headers, data=data1)  # , allow_redirects=False  302->301->200
print('')
print('登录后返回的响应session中的cookie(包含请求和响应):', session.cookies)
print('经过302->301->200 最后的cookie', response.cookies)  # 这是最后相应给302的索引为空

print('')
print(response.status_code)
print(response.url)
print(response.headers)
print(response.headers.get('Location'))

with open('gushu.html', 'w', encoding='utf-8') as f:
    f.write(response.text)

当然如果我在最后的response的时候加上allow_redirects=False,那么我得到的将是它302跳转的Location页面,这一遍可以get()到location,而不加的话它会自动返回跳转后的200页面。

附加:

对于一些小白可能不知道这个打码平台怎么用,我这里加两张截图。

首先点我上面说的链接注册账号充值个几块钱。然后点击开发文档 ,选择自己的语言:

cv到你的项目目录下就行,代码应该一看就懂。 

猜你喜欢

转载自blog.csdn.net/suic009/article/details/122667207
今日推荐