反扒机制代理操作及验证码的识别

反扒机制:代理操作

代理操作:

  • 在爬虫中,所谓的代理指的是什么?

    • 就是代理服务器
  • 代理服务器的作用:

    • 就是用来转发请求和响应的
  • 在爬虫中为什么需要使用代理服务器:

    • 如果我们的爬虫对服务器短时间内发出高频请求。那么服务器检测到这样一个异常请求,就会将该请求的对应设备IP禁掉,这样就无法给服务器发请求获取数据了!
    • 如果ip被禁,我们就可以使用代理服务器进行请求转发,破解ip被禁的反爬机制。因为使用代理后,服务器端接受到的请求对应的ip地址就是代理服务器而不是我们真正的客户端的。
  • 代理服务器分为不同的匿名度:
    - 透明代理:如果使用了该形式的代理,服务器端知道你使用了代理机制也知道你的真实ip。
    - 匿名代理:知道你使用代理,但是不知道你的真实ip
    - 高匿代理:不知道你使用了代理也不知道你的真实ip
    - 代理的类型
    - https:代理只能转发https协议的请求
    - http:转发http的请求
    - 代理服务器:
    - 快代理
    - 西祠代理
    - goubanjia
    - 代理精灵(推荐):http://http.zhiliandaili.cn/)

    • 封装一个代理池

      from lxml import etree
      #以下这网址就是你用代理。代理给你的
      url = 'http://t.11jsq.com/index.php/api/entry?method=proxyServer.generate_api_url&packid=1&fa=0&fetch_key=&groupid=0&qty=4&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 = {
              'http':proxy
          }
          http_proxy.append(dic)
      http_proxy
      结果;
      [{'http': '58.243.28.218:33503'},
       {'http': '114.106.151.234:10566'},
       {'http': '114.252.50.79:11484'},
       {'http': '106.7.4.131:28803'}]
      

      对西祠代理发起一个高频的请求,让其将我本机ip禁掉

      url = 'https://www.xicidaili.com/nn/%d'
      ips = []
      for page in range(1,11):
          new_url = format(url%page)
          page_text = requests.get(url=new_url,headers=headers).text
          tree = etree.HTML(page_text)
          #在xpath表达式中不可以出现tbody标签
          tr_list = tree.xpath('//*[@id="ip_list"]//tr')[1:]
          for tr in tr_list:
              ip = tr.xpath('./td[2]/text()')[0]
              ips.append(ip)
      print(len(ips))
      

      使用代理机制破解ip被封的效果

      #代理池对应的代码
      url = 'http://ip.11jsq.com/index.php/api/entry?method=proxyServer.generate_api_url&packid=1&fa=0&fetch_key=&groupid=0&qty=29&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)
      
      #url模板
      url = 'https://www.xicidaili.com/nn/%d'
      ips = []
      for page in range(1,11):
          new_url = format(url%page)
          #让当次的请求使用代理机制,就可以更换请求的ip地址
          #requests模块有代理参数!!
          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="ip_list"]//tr')[1:]
          for tr in tr_list:
              ip = tr.xpath('./td[2]/text()')[0]
              ips.append(ip)
      print(len(ips))
              
      

验证码的识别

  • 基于线上的打码平台识别验证码

  • 打码平台

    • 1.超级鹰(使用):

      http://www.chaojiying.com/about.html

      • 1.注册【用户中心的身份】
      • 2.登录(用户中心的身份)
        • 1.查询余额,请充值
        • 2.创建一个软件ID(899370)
        • 3.下载示例代码
    • 2.云打码

    • 3.打码兔

    这是超级鹰的示例代码
    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('bobo328410948', 'bobo328410948', '899370')
        im = open(imgPath, 'rb').read()
        return chaojiying.PostPic(im,imgType)['pic_str']
    print(tranformImgCode('./a.jpg',1902))
    7261
    

    模拟登录

    • 流程:
      • 对点击登录按钮对应的请求进行发送(post请求)
      • 处理请求参数:
        • 用户名
        • 密码
        • 验证码
        • 其他的防伪参数
    #这里别忘记带上cookie!!!
    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
    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.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx'
    data = {
        '__VIEWSTATE': '4iQUDYGYp480//d8dSe+k037Ut9ijESlrJJLPgCEsA+C4EAmEQV4h+p/G4sKwsGz2mFdGeIE+TS8T6Gru2w14b4n2qfsxdeB4caV4zXWhLNTbDM9m/heuikk8S4=',
        '__VIEWSTATEGENERATOR': 'C93BE1AE',
        'from': 'http://so.gushiwen.org/user/collect.aspx',
        'email': 'www.zhangbowudi@qq.com',
        'pwd': 'bobo328410948',
        'code': code_text,#动态变化
        'denglu': '登录',
    }
    #对点击登录按钮发起请求:获取了登录成功后对应的页面源码数据
    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)
       
    

发现上图参数中有2组乱码参数。

  • 在请求参数中如果看到了一组乱序的请求参数,最好去验证码这组请求参数是否为动态变化。

  • 处理:

    • 方式1:常规来讲一半动态变化的请求参数会被隐藏在前台页面中,那么我们就要去前台页面源码中取找。

- 方式2:如果前台页面没有的话,我们就可以基于抓包工具进行全局搜索。
原文地址:https://www.cnblogs.com/zzsy/p/12687652.html