验证码识别
验证码与爬虫:
反爬机制:验证码。识别验证码图片中的数据,用于模拟登陆操作。
识别验证码的操作:
-
人工肉眼识别(不推荐)
-
第三方自动识别
云码使用流程:
-
注册:普通和开发者用户
-
登陆
-
普通用户的登录:查询该用户是否有剩余积分
-
开发者用户登录:下载示例代码
-
超级鹰使用流程:
-
注册:普通用户
-
登陆
-
题分查询
-
创建一个软件(id)
-
下载示例代码
-
使用打码平台识别验证码的编码流程
-
将验证码图片下载到本地
-
调用平台提供的示例代码进行图片数据识别
示例:识别古诗文网登陆页面中的验证码
古诗文网登陆页面url:登录古诗文网
以下代码以超级鹰为例:
import requests
from lxml import etree
import chaojiying
# 将验证码图片下载到本地
url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'
headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36'
}
page_text = requests.post(url=url, headers=headers).text
# 解析验证码图片img中的src属性值
tree = etree.HTML(page_text)
code_img_src = 'https://so.gushiwen.cn' + tree.xpath('//form/div[4]/div[4]//img/@src')[0]
img_data = requests.post(url=code_img_src, headers=headers).content
with open('pic.jpg', 'wb') as fp:
fp.write(img_data)
# 调用打码平台程序进行验证码数据识别
chaojiying.getCodeText()
模拟登陆
爬取基于某些用户的用户信息。
示例:对古诗文网进行模拟登陆
-
点击登陆按钮后会发起一个post请求
-
post请求中会携带登陆之前录入的相关的登录信息
-
验证码:每次请求都会动态变化
编码流程:
-
验证码识别,获取验证码图片的文字数据
-
发起post请求(请求处理参数)
-
对响应数据进行持久化存储
import requests
from lxml import etree
import chaojiying
if __name__ == '__main__':
url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'
headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36'
}
page_text = requests.post(url=url, headers=headers).text
# 对验证码图片进行捕获和识别
tree = etree.HTML(page_text)
code_img_src = 'https://so.gushiwen.cn' + tree.xpath('//form/div[4]/div[4]//img/@src')[0]
code_img_data = requests.post(url=code_img_src, headers=headers).content
with open('./pic.jpg', 'wb') as fp:
fp.write(code_img_data)
# 使用超级鹰对验证码图片进行识别
code = chaojiying.getCodeText()['pic_str']
print(code)
# 模拟登录
login_url = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'
data = {
'__VIEWSTATE': '6UFDtTwiCflWY5EZjQYE / 9gLf0mpITgmW1GeduQfl5O73ttOJqoqKCyVDrr29ga23W7v7CNho6gK + oJF6EoA / pAj9IucvYHA7Y1KGIq03ambAvVGsVmwsLSKyv6IvyzzrCSc8psy9M3ZzT2HQitTTjBCV2o =',
'__VIEWSTATEGENERATOR': 'C93BE1AE',
'from': 'http: // so.gushiwen.cn / user / collect.aspx',
'email': '2072164234 @ qq.com',
'pwd': 'roy11081003',
'code': code,
'denglu': '登录'
}
response = requests.post(url=login_url, headers=headers, data=data)
login_page_text = response.text
print(response.status_code) # 响应状态码为200则表示响应成功
with open('./gushiwenwang.html', 'w', encoding='utf-8') as fp:
fp.write(login_page_text)
模拟登录cookie操作(session)
http/https协议特性:无状态(不会记录当前请求对应的状态)
cookie
让服务器端记录客户端的相关状态
-
手动处理:通过抓包工具获取cookie值,将该值封装到headers中
-
自动处理:
-
cookie值的来源:进行模拟登录请求后,由服务器端创建
-
session会话对象
-
可以进行请求的发送
-
如果请求过程中产生了cookie,则该cookie会被自动存储/携带在该session对象中
-
-
编码流程:
-
创建一个session对象:session = requests.Session()
-
使用session对象进行模拟登录post请求的发送(cookie就会被存储在session对象中)
-
session对象对个人主页对应的get请求进行发送(携带了cookie)
import requests
from lxml import etree
import chaojiying
if __name__ == '__main__':
url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'
# 创建一个session对象
session = requests.Session()
headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36'
}
# 使用session进行post请求的发送
page_text = session.post(url=url, headers=headers).text
# 对验证码图片进行捕获和识别
tree = etree.HTML(page_text)
code_img_src = 'https://so.gushiwen.cn' + tree.xpath('//form/div[4]/div[4]//img/@src')[0]
code_img_data = requests.post(url=code_img_src, headers=headers).content
with open('./pic.jpg', 'wb') as fp:
fp.write(code_img_data)
# 使用超级鹰对验证码图片进行识别
code = chaojiying.getCodeText()['pic_str']
print(code)
# 模拟登录
login_url = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'
data = {
'__VIEWSTATE': '6UFDtTwiCflWY5EZjQYE / 9gLf0mpITgmW1GeduQfl5O73ttOJqoqKCyVDrr29ga23W7v7CNho6gK + oJF6EoA / pAj9IucvYHA7Y1KGIq03ambAvVGsVmwsLSKyv6IvyzzrCSc8psy9M3ZzT2HQitTTjBCV2o =',
'__VIEWSTATEGENERATOR': 'C93BE1AE',
'from': 'http: // so.gushiwen.cn / user / collect.aspx',
'email': '2072164234 @ qq.com',
'pwd': 'roy11081003',
'code': code,
'denglu': '登录'
}
# 使用session进行post请求的发送
response = session.post(url=login_url, headers=headers, data=data)
login_page_text = response.text
print(response.status_code)
# with open('./gushiwenwang.html', 'w', encoding='utf-8') as fp:
# fp.write(login_page_text)
# 获取个人主页信息
# 使用携带cookie的session进行get请求的发送
detail_url = 'https://so.gushiwen.cn/user/collect.aspx'
detail_page_text = session.get(url=detail_url, headers=headers).text
with open('./detail.html', 'w', encoding='utf-8') as fp:
fp.write(detail_page_text)
代理
破解封IP这种反爬机制
代理:代理服务器
代理的作用:
-
突破自身IP访问的限制
-
隐藏自身真实的IP
代理相关的网站:
-
快代理
-
西祠代理
代理IP的类型:
-
http:应用到http协议对应的url中
-
https:应用到https协议对应的url中
代理IP的匿名度:
-
透明:服务器知道该次请求使用了代理,也知道请求对应的真实IP
-
匿名:知道使用了代理,不知道真实IP
-
高匿:不知道使用了代理,更不知道真实的IP
import requests
url = 'https://www.baidu.com/s?wd=ip'
headers = {
'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Mobile Safari/537.36'
}
# 先将请求发送到代理服务器,代理服务器把请求发送到真实的服务器
page_text = requests.get(url=url, headers=headers, proxies={'https': '104.129.198.36'}).text
with open('./ip.html', 'w', encoding='utf-8') as fp:
fp.write(page_text)