爬蟲中的模擬登錄,IP代理,線程池

模擬登錄

  • 爲何要進行模擬登錄html

    • 有些時候,咱們須要爬取一些基於我的用戶的用戶信息(須要登陸後才能夠查看的)
  • 爲何須要識別驗證碼python

    • 由於驗證碼每每是做爲登陸請求中的請求參數被使用
  • 驗證碼識別:藉助於線上的一款打碼平臺(超級鷹,雲打碼,打碼兔)服務器

  • 超級鷹的使用流程:http://www.chaojiying.com/about.htmlcookie

    • 註冊:註冊一個 <用戶中心> 身份的帳號
    • 登陸:基於 <用戶中心> 進行登陸
    • 點擊 軟件ID -->生成一個軟件id
    • 下載示例代碼:點擊開發文檔->選擇python語言->點擊下載
  • 實現模擬登錄網絡

    • 就是使用抓包工具捕獲登陸按鈕對應的post請求數據包,從該數據包中提取出請求的url和請求參數,就可使用requests進行請求發送
  • cookie操做:session

    • 手動處理(不建議):
      • 將cookie放置到headers中,靈活性差,cookie存儲有時間上限
    • 自動處理(建議):使用requests模塊中的Session對象:
      • Session對象:該對象能夠像requests同樣發送get和post請求,當該對象在進行請求發送的過程當中,產生cookie,則該cookie會被自動存儲到該對象中
        • session = requests.Session()
  • 模擬登錄案例app

    #模擬登錄爬取古詩文網站登錄界面
    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的錯誤dom

    • 緣由
      • 請求池資源被耗盡,在headers中加入一個鍵值對:'Connection':'close'
      • 請求ip被服務器禁用
        • 可使用代理IP解決
  • 代理:異步

    • 概念:代理服務器
    • 代理IP:代理服務器的ip
    • 代理IP網站:快代理、西祠代理、goubanjia
    • 代理方式及參數
      • get/post(url,headers,data/params,proxies={'http':'ip:port'})
  • 什麼是高匿名、匿名和透明代理?他們有什麼區別?jsp

    • 使用透明代理,對方服務器能夠知道你使用了代理,而且也知道你的真實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";
    """
相關文章
相關標籤/搜索