ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

04 requests 高级(cookie,代理,验证码识别)

2021-09-19 12:00:45  阅读:139  来源: 互联网

标签:请求 04 url text 代理 headers cookie requests


requests 高级

  • cookie
  • 代理机制
  • 验证码的识别
  • 模拟登录

1. cookie介绍

  • cookie:
    • 是存储在客户端的一组键值对。
    • web中cookie的典型应用:
      • 免密登录
    • cookie和爬虫之间的关联
      • 有时候,对一张页面进行请求的时候,如果请求的过程中不携带cookie的话,那么我们是无法请求到正确的页面数据。因此cookie是爬虫中一个非常典型且常见的反爬机制。
  • 需求:爬取雪球网中的咨询信息。https://xueqiu.com/
  • 分析:
    • 1.判定爬取的咨询数据是否为动态加载的
      • 相关的更多咨询数据是动态加载的,滚轮滑动到底部的时候会动态加载出更多咨询数据。
    • 2.定位到ajax请求的数据包,提取出请求的url,响应数据为json形式的咨询数据
headers = {
    'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
}
url = 'https://xueqiu.com/statuses/hot/listV2.json?since_id=-1&max_id=256028&size=15'
page_text = requests.get(url=url,headers=headers).json()
page_text

注意:上述代码后会出现获取不到动态ajax动态加载的数据,因为该网站需要携带cookie发起请求,才能获得动态加载的数据。cookie是从服务端开始的,需要看服务端编写规则。这也是一种反爬机制。

  • 上述代码问题:没有请求到我们想要的数据

  • 原因:没有严格意义上模拟浏览器发请求

    • 处理:可以将浏览器发请求携带的请求头(有很多,不是只有cookie,cookie只是优先考虑),全部粘贴在headers字典中,将headers作用到requests的请求操作中即可。
  • 一般我们会先添加cookie到请求头中

  • cookie的处理方式

    • 方式一:手动处理
      • 将抓包工具中的cookie粘贴在headers中
      • 弊端:cookie如果过了有效时长可能会失效
    • 方式二:自动处理
      • 基于Session对象实现自动处理
      • 如何过去一个Session对象:requests.Session()返回一个session对象。
      • session对象的作用:
        • 该对象可以向requests一样调用get和post发起指定的请求。只不过如果在使用session发请求的过程中如果产生了cookie,则cookie会被自动存储到该session对象中,那么就意味着下次再次使用session对象发起请求,则该次请求就是携带cookie进行的请求发送。
      • 在爬虫中使用session的时候,session对象至少会被使用几次?
        • 两次。第一次使用session是为了将cookie捕获且存储到session对象中。下次的时候就是携带cookie进行的请求发送。
# 自动处理cookie 方式
session = requests.Session()
main_url = 'https://xueqiu.com/'
session.get(main_url,headers=headers)#捕获且存储cookie

url = 'https://xueqiu.com/statuses/hot/listV2.json?since_id=-1&max_id=256028&size=15'
page_text = session.get(url=url,headers=headers).json() #携带cookie发起的请求
page_text

注意:通过Session获取cookie时,不一定访问首页后Session就会携带cookie,cookie可能出现在其他子页面上,需要去不断测试寻找,因此 在实操的时候更多采用方式一手动添加cookie,虽然会有时效,但是时间一般不会太短5-10分组,时间足够。

2. 代理

  • 代理操作
    • 在爬虫中,所谓的代理指的是什么?
      • 就是代理服务器
    • 代理服务器的作用是什么?
      • 就是用来转发请求和响应。
# 没有代理的时候
	客户端 --->  服务端
# 有代理的时候
	客户端 --->代理--->  服务端
  • 代理操作
    • 在爬虫中,所谓的代理指的是什么?
      • 就是代理服务器
    • 代理服务器的作用是什么?
      • 就是用来转发请求和响应。
    • 在爬虫中为什么需要使用代理服务器?
      • 如果我们的爬虫在短时间内对服务器发起了高频的请求,那么服务器会检测到这样的一个异常的行为请求,就会将该请求对应设备的ip禁掉,就以为这client设备无法对服务器端再次进行请求发送。(ip被禁掉了)
      • 如果ip被禁,我们就可以使用代理服务器进行请求转发,破解ip被禁的反爬机制。因为使用代理后,服务器端接受到的请求对应的ip地址就是代理服务器而不是我们真正的客户端的。
    • 代理服务器分为不同的匿名度:
      • 透明代理:如果使用了该形式的代理,服务器端知道你使用了代理机制也知道你的真实ip。
      • 匿名代理:知道你使用代理,但是不知道你的真实ip
      • 高匿代理:不知道你使用了代理也不知道你的真实ip
    • 代理的类型
      • https:代理只能转发https协议的请求
      • http:转发http的请求
    • 代理服务器:

注意: 说明一下,这里的三种代理服务器都能用,并不是说透明代理不能使用,我们的目的只是在网站封了我们的ip之后,我们可以通过代理服务器去再次访问这个网站,所以服务器不管知不知道本身ip,都能访问网站。同理高匿代理也不是说明事情都能干,虽然服务端不知道你的ip,但是做了违法的事情只需要找到代理商同样可以找到自身ip。代理会有转发效率问题

# 首先使用获取快代理中的数据(没有被禁掉ip之前,也会出现部分数据获取不到的问题,使用代理之后都能获取到),让网站禁掉我的ip, 然后再使用自己购买的ip进行重新爬取。
	# 先构建代理池,然后随机获取代理发起请求

#代理池对应的代码
url = 'http://t.ipjldl.com/index.php/api/entry?method=proxyServer.generate_api_url&packid=1&fa=0&fetch_key=&groupid=0&qty=28&time=1&pro=&city=&port=1&format=html&ss=5&css=&dt=1&specialTxt=3&specialJson=&usertype=2'     # 这时有代理的网站
page_text = requests.get(url,headers=headers).text
tree = etree.HTML(page_text)
proxy_list = tree.xpath('//body//text()')
http_proxy = [] #代理池

for proxy in proxy_list:
    dic = {
        'https':proxy
    }
    http_proxy.append(dic)
print(http_proxy)
#url模板
url = 'https://www.kuaidaili.com/free/inha/%d/'
ips = []
for page in range(1,11):
    new_url = format(url%page)
    #让当次的请求使用代理机制,就可以更换请求的ip地址
    page_text = requests.get(url=new_url,headers=headers,proxies=random.choice(http_proxy)).text
    tree = etree.HTML(page_text)
    #在xpath表达式中不可以出现tbody标签
    tr_list = tree.xpath('//*[@id="list"]/table//tr')[1:]
    print(len(tr_list))
    for tr in tr_list:
        ip = tr.xpath('./td[1]/text()')
        ips.append(ip)
print(len(ips))

3. 简单模拟登录

  • 使用超级鹰(注册--购买积分--下载代码--查看使用说明--调用就行)
#!/usr/bin/env python
# coding:utf-8

"""超级鹰代码"""
import requests
from hashlib import md5

class Chaojiying_Client(object):

    def __init__(self, username, password, soft_id):
        self.username = username
        password =  password.encode('utf8')
        self.password = md5(password).hexdigest()
        self.soft_id = soft_id
        self.base_params = {
            'user': self.username,
            'pass2': self.password,
            'softid': self.soft_id,
        }
        self.headers = {
            'Connection': 'Keep-Alive',
            'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
        }

    def PostPic(self, im, codetype):
        """
        im: 图片字节
        codetype: 题目类型 参考 http://www.chaojiying.com/price.html
        """
        params = {
            'codetype': codetype,
        }
        params.update(self.base_params)
        files = {'userfile': ('ccc.jpg', im)}
        r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files, headers=self.headers)
        return r.json()

    def ReportError(self, im_id):
        """
        im_id:报错题目的图片ID
        """
        params = {
            'id': im_id,
        }
        params.update(self.base_params)
        r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
        return r.json()
	
"""调用该函数对图片进行识别, 图片必须是下载到本地的"""
def tranformImgCode(imgPath,imgType):
    chaojiying = Chaojiying_Client('xxx', 'xxx', 'xxx')   # xxx 是自己的用户名 具体下载下来的压缩包有说明。。。
    im = open(imgPath, 'rb').read()
    return chaojiying.PostPic(im,imgType)['pic_str']

tranformImgCode("./a.jpg", 1902)       # 1902 是图片类型

4. 综合案例

session = requests.Session()

#识别验证码
url = 'https://so.gushiwen.org/user/login.aspx?from=http://so.gushiwen.org/user/collect.aspx'
page_text = session.get(url=url,headers=headers).text
#解析验证码图片的地址
tree = etree.HTML(page_text)
img_src = 'https://so.gushiwen.org'+tree.xpath('//*[@id="imgCode"]/@src')[0]
#将验证码图片保存到本地
img_data = session.get(img_src,headers=headers).content

# 处理参数中动态的乱序的key
tree = etree.HTML(page_text)
viewstate_value = tree.xpath('//*[@id="__VIEWSTATE"]/@value')[0]
viewstate_value = str(viewstate_value)
print(viewstate_value, type(viewstate_value))

with open('./code.jpg','wb') as fp:
    fp.write(img_data)

#识别验证码
code_text = tranformImgCode('./code.jpg',1902)
print(code_text)
login_url ='https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'
data = {
    '__VIEWSTATE': viewstate_value,
    '__VIEWSTATEGENERATOR': 'C93BE1AE',
    'from': 'http://so.gushiwen.cn/user/collect.aspx',
    'email': '19126193936',
    'pwd': 'leo521221',
    'code': code_text,#动态变化
    'denglu': '登录',
}
print(data)
#对点击登录按钮发起请求:获取了登录成功后对应的页面源码数据
page_text_login = session.post(url=login_url,headers=headers,data=data).text

with open('./gushiwen.html','w',encoding='utf-8') as fp:
    fp.write(page_text_login)

标签:请求,04,url,text,代理,headers,cookie,requests
来源: https://www.cnblogs.com/yebaoer/p/15302589.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有