本人也是菜鸟一枚如有大佬看到就慢慢看我装逼,若有新如坑的小伙伴我们一起加油。
在众多的反爬手段中验证码可以说是比较有效的手段之一了,今天写了一个模拟登陆的程序与大家分享,也做为自己的一次总结。
要爬取的目标网站:
https://so.gushiwen.org
先来说一下关于验证码这块的处理,惯用的有三种方法:
一是将验证码下载到本地,然后手动在键盘上输入。这种方法是最保险的方法,但也是效率最低的方法,使用于爬虫任务量不是很大,对爬虫效率没有较高的要求的情况。
二是采用tesseract库,这种方法对一些简单的图形验证码来说还是有用的,像纯字母或纯数字这种对图片做一些简单的处理即可,比如二值化、转灰度等。是不是很方便?如果你觉得很方便的话,那你就错了!这种操作有6张验证码能识别出3到4张就很牛逼了,但这还是达不到我们的要求怎么办,那就机器学习,今天不做深究。
三是用打码平台,这种方法呢,我会单独的写一篇详细的用法。暂且不提。
思路:
1.向登陆页面发送get请求,获取到响应内容后拿自己用得最6的解析方式,将验证码图片的SRC取出来。
import requests
import urllib.request
from lxml import etree
s = requests.session()
url = ‘https://so.gushiwen.org/user/login.aspx?’
headers = {
‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) ‘
‘Chrome/70.0.3538.110 Safari/537.36’
}
r = requests.get(url=url,headers=headers)
tree = etree.HTML(r.text)
img_src = tree.xpath(‘//div[@class=”mainreg2″][3]/img[@id=”imgCode”]/@src’)[0]
2.验证码的完整地址是:https://so.gushiwen.org/RandCode.ashx,就是拼接嘛,然后向拼接完成的URL发送get请求下载验证码图片。
urllib.request.urlretrieve(image_src,’code.png’)
3.抓包分析或者采用开发者工具找到登陆所需的参数,这一步呢比较建议使用fiddler抓包工具,因为在开发者工具中登陆所需的参数分布在不同的字段中,有时会找不齐(我就爬过这个坑),在fiddler中的请求详情中的Webforms一栏中会包含所有登陆所需的参数和登陆的接口。
登陆的接口:https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx
登陆所需的参数:
‘__VIEWSTATE’:CsLDIp5JJGJCCuh76ipinjcqzhHVS2uRMHJ7JkXtVRllfxUzqBZuaRuwISfGf0aEGQCbecVIRKF76hW+VixVlqygRBZx9fAUn3foAXqf7YR2tuYNnDtLB/+dL8E=,
‘__VIEWSTATEGENERATOR’:C93BE1AE,
‘from’:’http://so.gushiwen.org/user/collect.aspx’,
’email’:’这个是账号’,
‘pwd’:’这个是密码’,
‘code’:code, #这个是验证码
‘denglu’:’登陆’,
4.向这个登陆接口发送post请求。
url = ‘https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx’
code = input(‘请输入验证码:’)
formdata = { ‘__VIEWSTATE’:CsLDIp5JJGJCCuh76ipinjcqzhHVS2uRMHJ7JkXtVRllfxUzqBZuaRuwISfGf0aEGQCbecVIRKF76hW+VixVlqygRBZx9fAUn3foAXqf7YR2tuYNnDtLB/+dL8E=,
‘__VIEWSTATEGENERATOR’:C93BE1AE,
‘from’:’http://so.gushiwen.org/user/collect.aspx’,
’email’:’erer4564654@163.com’,
‘pwd’:’lakers24kebi’,
‘code’:code,
‘denglu’:’登陆’,
}
r = s.post(url=post_url,headers=headers,data=formdata)
print(r.text)
打印一下看响应内容,如果有修改密码、账号管理等内容证明登陆成功。
然鹅。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
报错!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
是错在哪里呢?
发送请求、解析内容、下载图片又发送请求都没错啊,咋会报错呢,这时我们就应当分析一下登陆接口所需的参数了,__VIEWSTATE和__VIEWSTATEGENERATOR这两个参数都有各自的值他们会根据请求而随机改变这个名词叫表单令牌不能写死,且他们能在源码中找到,那就获取他们在源码中的路径表达式来代替formdata中的参数值。
__VIEWSTATE =tree.xpath(‘//form[@name=”aspnetForm”]/div[1]/input[@id=”__VIEWSTATE”]/@value’)[1]
__VIEWSTATEGENERATOR =tree.xpath(‘//form[@name=”aspnetForm”]/div[2]/input[@id=”__VIEWSTATEGENERATOR”]/@value’)[1]
[0]这个的意思是,在xpath中路径表达式获取的是一个列表,而我要的是其中一个元素,xpath的索引是从1开始的(python中的索引和jsonpath从0开始的)。
再向登陆接口发一次请求,
post_url = ‘https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx’
code = input(‘请输入验证码:’)
formdata = {
‘__VIEWSTATE’:__VIEWSTATE,
‘__VIEWSTATEGENERATOR’:__VIEWSTATEGENERATOR,
‘from’:’http://so.gushiwen.org/user/collect.aspx’,
’email’:’erer4564654@163.com’,
‘pwd’:’lakers24kebi’,
‘code’:code,
‘denglu’:’登陆’,
}
r = s.post(url=post_url,headers=headers,data=formdata)
print(r.text)
这次应该没问题了吧,呵呵。
还是报错!
这次出错的原因是没有维持同一会话,这个以后也会单独写一篇。
怎么解决呢?用s = requests.session()即可解决。那所有的请求就要采用这种方式了。
完整的源码:
import requests
import urllib.request
from lxml import etree
s = requests.session()
url = ‘https://so.gushiwen.org/user/login.aspx?’
headers = {
‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) ‘
‘Chrome/70.0.3538.110 Safari/537.36’
}
发送get请求获取验证码的URL
r = s.get(url=url,headers=headers)
tree = etree.HTML(r.text)
img_src = tree.xpath(‘//div[@class=”mainreg2″][3]/img[@id=”imgCode”]/@src’)[0]
拼接URL将验证码下载到本地
image_src = ‘https://so.gushiwen.org’ + str(img_src)
r_image = s.get(url=image_src,headers=headers)
with open(‘code.png’,’wb’) as fp:
fp.write(r_image.content)
解析获得登陆所需的参数
__VIEWSTATE =tree.xpath(‘//form[@name=”aspnetForm”]/div[1]/input[@id=”__VIEWSTATE”]/@value’)[0]
__VIEWSTATEGENERATOR =tree.xpath(‘//form[@name=”aspnetForm”]/div[2]/input[@id=”__VIEWSTATEGENERATOR”]/@value’)[0]
登陆网站验证是否登陆成功
post_url = ‘https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx’
code = input(‘请输入验证码:’)
formdata = {
‘__VIEWSTATE’:__VIEWSTATE,
‘__VIEWSTATEGENERATOR’:__VIEWSTATEGENERATOR,
‘from’:’http://so.gushiwen.org/user/collect.aspx’,
’email’:’erer4564654@163.com’,
‘pwd’:’lakers24kebi’,
‘code’:code,
‘denglu’:’登陆’,
}
r = s.post(url=post_url,headers=headers,data=formdata)
print(r.text)
总结:1.要以对话的形式发送每一次请求
2.先发get,再发get,最后发post
装逼结束,我宣布退出装逼界!

文章来源于互联网:爬虫技能——代码模拟验证码登录网站之初级版

发表评论