zoukankan      html  css  js  c++  java
  • 爬虫中的模拟登陆,IP代理,线程池

    模拟登陆

    • 为什么要进行模拟登陆

      • 有些时候,我们需要爬取一些基于个人用户的用户信息(需要登录后才可以查看的)
    • 为什么需要识别验证码

      • 因为验证码往往是作为登录请求中的请求参数被使用
    • 验证码识别:借助于线上的一款打码平台(超级鹰,云打码,打码兔)

    • 超级鹰的使用流程:http://www.chaojiying.com/about.html

      • 注册:注册一个<用户中心>身份的账号
      • 登录:基于<用户中心>进行登录
      • 点击 软件ID -->生成一个软件id
      • 下载示例代码:点击开发文档->选择python语言->点击下载
    • 实现模拟登陆

      • 就是使用抓包工具捕获登录按钮对应的post请求数据包,从该数据包中提取出请求的url和请求参数,就可以使用requests进行请求发送
    • cookie操作:

      • 手动处理(不建议):
        • 将cookie放置到headers中,灵活性差,cookie存储有时间上限
      • 自动处理(建议):使用requests模块中的Session对象:
        • Session对象:该对象可以像requests一样发送get和post请求,当该对象在进行请求发送的过程中,产生cookie,则该cookie会被自动存储到该对象中
          • session = requests.Session()
    • 模拟登陆案例

      #模拟登陆爬取古诗文网站登陆界面
      import requests
      from lxml import etree
      from chaojiying_Python.chaojiying import Chaojiying_Client
      
      #当你处理登陆爬虫时要将请求换成session
      session = requests.Session()
      #将超级鹰下载的包封装成一个函数进行引入调用
      def get_codeImg_text(imgPath, imgType):
          chaojiying = Chaojiying_Client('超级鹰账号', '超级鹰密码', '	899991')	#用户中心>>软件ID 生成一个替换 96001
          im = open(imgPath, 'rb').read()													#本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
          # print(chaojiying.PostPic(im, 1902))
          return chaojiying.PostPic(im, imgType)['pic_str']
      
      headers = {
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
      }
      
      #模拟登录
      #获取验证码图片
      url = 'https://so.gushiwen.org/user/login.aspx?from=http://so.gushiwen.org/user/collect.aspx'
      #解析验证码图片
      page_text = requests.get(url=url,headers=headers).text
      tree = etree.HTML(page_text)
      code_img_src = 'https://so.gushiwen.org/'+tree.xpath('//*[@id="imgCode"]/@src')[0]
      code_img_data = session.get(url=code_img_src,headers=headers).content
      with open('./code.jpg','wb') as fp:
          fp.write(code_img_data)
      #解析动态参数
      __VIEWSTATE = tree.xpath('//input[@id="__VIEWSTATE"]/@value')[0]
      __VIEWSTATEGENERATOR = tree.xpath('//input[@id="__VIEWSTATEGENERATOR"]/@value')[0]
      print(__VIEWSTATE,__VIEWSTATEGENERATOR)
      #使用打码平台识别出来的验证码图片数据
      codeImg_text = get_codeImg_text('./code.jpg',1902)
      print(codeImg_text)
      login_url = 'https://so.gushiwen.org/user/login.aspx?from=http%3a%2f%2fso.gushiwen.org%2fuser%2fcollect.aspx'
      #动态参数:动态参数往往都会被隐藏在前台页面
      data = {
          #处理了动态参数
          "__VIEWSTATE": __VIEWSTATE,
          "__VIEWSTATEGENERATOR": __VIEWSTATEGENERATOR,
          "from": "http://so.gushiwen.org/user/collect.aspx",
          "email": "你的账号",
          "pwd": "你的密码",
          "code": codeImg_text,
          "denglu": "登录",
      }
      #登陆发送post请求,且传送data
      pages_text = session.post(url=login_url,headers=headers,data=data).text
      with open('./gushiwen.html','w',encoding='utf-8') as fp:
          fp.write(pages_text)
      

    代理IP

    • 在爬取数据的时候可能会报出一个HttpConnectilonPool的错误

      • 原因
        • 请求池资源被耗尽,在headers中加入一个键值对:'Connection':'close'
        • 请求ip被服务器禁用
          • 可以使用代理IP解决
    • 代理:

      • 概念:代理服务器
      • 代理IP:代理服务器的ip
      • 代理IP网站:快代理、西祠代理、goubanjia
      • 代理方式及参数
        • get/post(url,headers,data/params,proxies={'http':'ip:port'})
    • 什么是高匿名、匿名和透明代理?他们有什么区别?

      • 使用透明代理,对方服务器可以知道你使用了代理,并且也知道你的真实IP
      • 使用匿名代理.对方服务器可以知道你使用了代理,但不知道你的真实IP
      • 使用高匿名代理:对方服务器不知道你使用了代理,更不知道你的真实IP
    • 类型:

      • http:只可以发起http请求
      • https:只可以发起https请求
    • 简单的ip代理演示

      url = 'https://www.baidu.com/s?wd=ip'
      page_text = requests.get(url=url,headers=headers,proxies={'http':'177.91.254.51:9999'})
      with open('./ip.html','w',encoding='utf-8') as fp
      	fp.wirte(page_text)
      
    • 代理IP被封如何解决?

    线程池

    • 线程池:尽可能用在耗时较为严重的操作中

      • 视频的请求下载

      • 视频的持久化存储

      • 使用模块

        #模块引入
        from multiprocessing.dummy import Pool
        
        #创建线程数量
        pool = Pool(4)
        
        pool.map(func,iterable,chunksize=None)
        #map方法可以基于异步实现:让参数1对应的函数对参数2对应的容器元素一次进行操作,参数二必须是可迭代的,比如最典型的列表
        
        
    • 模拟请求阻塞操作

      • 普通的访问方式
      普通的访问方式
      import time
      def my_request(url):
          print('正在请求:',url)
          #设置了休眠等待
          time.sleep(10)
          print('请求完毕:', url)
      
      urls = [
          'www.1.com',
          'www.2.com',
          'www.3.com',
          'www.4.com',
      ]
      
      start = time.time()
      for url in urls:
          my_request(url)
      print(time.time()-start)
      
      • 使用线程池

        #使用线程池
        import time
        from multiprocessing.dummy import Pool
        pool = Pool(4)
        
        def my_request(url):
            print('正在请求:',url)
            time.sleep(10)
            print('请求完毕:', url)
        
        urls = [
            'www.1.com',
            'www.2.com',
            'www.3.com',
            'www.4.com',
        ]
        
        start = time.time()
        pool.map(my_request,urls)
        print(time.time()-start)
        pool.close()
        #join的意思是让主线程等待子线程全部结束后再结束
        pool.join()
        
    • 案例:对梨视频的视频爬取

      #对梨视频的视频爬取
      
      import re,random
      import requests
      from lxml import etree
      from multiprocessing.dummy import Pool
      pool = Pool(4)
      
      #定义一个函数,传送每一个url,下载视频
      def downloadDate(url):
          #content爬取二进制使用
          return requests.get(url=url,headers=headers).content
      #定义一个函数,存储每一个视频
      def saveDate(data):
          name = str(random.randint(0,10000))+'mp4'
          with open(name,'wb') as fp:
              fp.write(data)
          print(name,'下载成功')
      url = 'https://www.pearvideo.com/category_1'
      headers = {
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
      }
      
      page_text = requests.get(url=url,headers=headers).text
      tree = etree.HTML(page_text)
      li_list = tree.xpath('//ul[@id="listvideoListUl"]/li')
      #定义一个空列表存放所有的视频链接
      urls = []
      for li in li_list:
          detail_url = 'https://www.pearvideo.com/'+li.xpath('./div/a/@href')[0]
          pages_text = requests.get(url=detail_url,headers=headers).text
          ex = 'srcUrl="(.*?)",vdoUrl'
          video_url = re.findall(ex,pages_text,re.S)[0]
          urls.append(video_url)
      #在耗时较为严重的地方使用线程池,视频的请求下载及持久化存储
      #让函数对urls中的每一个元素进行异步网络请求下载
      #函数不能传参,不能加括号
      #datas是一个列表,存储的是所有的视频二进制的数据
      datas = pool.map(downloadDate,urls)
      
      pool.map(saveDate,datas)
      
      pool.close()
      #join的意思是让主线程等待子线程全部结束后再结束
      pool.join()
      
      
      
      #在获取视频链接的时候发现视频并不是存储在标签中,而是在js中的变量里,
      # 此时我们只能使用支持各种匹配的正则来获取链接
      """
      var contId="1565375",liveStatusUrl="liveStatus.jsp",
      liveSta="",playSta="1",autoPlay=!1,isLiving=!1,isVrVideo=!1,
      hdflvUrl="",sdflvUrl="",hdUrl="",sdUrl="",ldUrl="",
      srcUrl="https://video.pearvideo.com/mp4/short/20190612/cont-1565375-14010027-hd.mp4",
      vdoUrl=srcUrl,skinRes="//www.pearvideo.com/domain/skin",videoCDN="//video.pearvideo.com";
      """
      
  • 相关阅读:
    十年经验手把手教你选购翡翠
    眼睛视力
    玻璃
    前端小技巧
    儿童牙齿矫正
    MySQL的JDBC驱动源码解析
    书海杂谈
    电子设备
    股市国家队
    影视
  • 原文地址:https://www.cnblogs.com/Godisgirl/p/11020292.html
Copyright © 2011-2022 走看看