爬蟲的三種數據解析方式和驗證碼的處理


1,正則解析:就是通過正則匹配定位到要獲取數據的標簽,獲取響應的數據

  • 直接上代碼(以爬取糗事百科為例)
import requests
import re import os if __name__ == '__main__': # 訪問請求的url url = "https://www.qiushibaike.com/pic/page/%s/" # 定制請求頭 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36" } # 指定其實和結束頁碼 page_start = input("請輸入起始頁碼:") page_end = input("請輸入結束頁碼:") # 創建文件夾 if not os.path.exists("images"): os.mkdir("images") # 循環解析且下載指定頁碼中的圖片數據 for page in range(int(page_start), int(page_end)+1): print("第%s頁圖片正在下載" % page) new_url = format(url % page) response = requests.get(url=new_url, headers=headers) # 解析response中的圖片鏈接 e = '<div class="thumb">.*?<img src="(.*?)".*?>.*?</div>' pa = re.compile(e, re.S) image_urls = pa.findall(response.text) # 循環下載該頁碼下的多有url圖片數據 for image_url in image_urls: image_url = "https:" + image_url image_name = image_url.split("/")[-1] image_path = "images/" + image_name image_data = requests.get(url=image_url, headers=headers).content # 存儲到本地 with open(image_path, "wb") as fp: fp.write(image_data)

2,xpath的表達式:是一種用來定位標簽的層級關系的一中表達式

 

  • xpath表達式的要點:
# 屬性定位:
    # 找到class屬性值為xuexue的div標簽
    //div[@class='xuexue']  # //表示多層目錄下
# 層級&索引定位:
    
    # 找到class屬性值為xue的div的直系子標簽ul下的第二個子標簽li下的直系a標簽
    //div[@class="xue"]/ul/li[2]/a  # xpath表達式支持索引,但索引是從1開始的
# 邏輯運算:
    # 找到href屬性值為空且class屬性值為du的a標簽
    //a[@href="" and @class="du"]  # xpath 表達式支持偶家運算
#模糊胡匹配:
    //div[contains(@class, "ng")]
    //div[starts-with(@class, "ta")] #取文本: #表示獲取某個標簽下的文本內容 #//表示獲取某個標簽下文本內容和所有子標簽下的文本內容 //div[@class="xuexue"]/p[1]/text() //div[@class="xuexue"]//text() # 取屬性: // div[@class="xuexue"]//li[2]/a/@href
  • 代碼中xpath表達式進行數據解析:
    1. 下載:pip install lxml
    2. 導包: from lxml import etree
    3. 將html文檔或xml文檔轉換成一個etree對象,然后調用對象中的方法查找指定的節點
      1. 本地文件: tree = etree.parse(文件名)    tree.xpath("xpath表達式")
      2. 網絡數據:tree = etree.HTML(網頁內容字符串)   tree.xpath("xpath表達式")
  • 安裝xpath插件在瀏覽器中對xpath表達式進行驗證:可以在插件中直接執行xpath表達式
    • 將xpath插件拖動到谷歌瀏覽器拓展程序(更多工具中),真能裝成功!!!
    • 啟動和關閉插件:ctrl + shift + x
  • 下載簡單中的圖片數據
import requests
from lxml import etree import base64 from urllib import request # 指定要訪問的url url = "http://jandan.net/ooxx" # 指定響應頭 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36" } page_text = requests.get(url=url, headers=headers).text tree = etree.HTML(page_text) imgCode_list = tree.xpath("//span[@class='img-hash']/text()") imgUrl_list = [] for url in imgCode_list: img_url = "http:" + base64.b64decode(url).decode() imgUrl_list.append(img_url) for url in imgUrl_list: filePath = url.split("/")[-1] request.urlretrieve(url=url, filename=filePath) print(filePath + "下載成功!") # 查看頁面源碼:發現所有圖片的src值都是一樣的。 #簡單觀察會發現每張圖片加載都是通過jandan_load_img(this)這個js函數實現的。 #在該函數后面還有一個class值為img-hash的標簽,里面存儲的是一組hash值,該值就是加密后的img地址 #加密就是通過js函數實現的,所以分析js函數,獲知加密方式,然后進行解密。 #通過抓包工具抓取起始url的數據包,在數據包中全局搜索js函數名(jandan_load_img),然后分析該函數實現加密的方式。 #在該js函數中發現有一個方法調用,該方法就是加密方式,對該方法進行搜索 #搜索到的方法中會發現base64和md5等字樣,md5是不可逆的所以優先考慮使用base64解密 #print(page_text) #在抓包工具的數據包響應對象對應的頁面中進行xpath的編寫,而不是在瀏覽器頁面中。 #獲取了加密的圖片url數據

3,BeautifulSoup解析

  • 環境的安裝
    1. 需要將pip原設置為國內源,阿里源,豆瓣源,網易源等
    2. windows
      1. 打開文件資源管理器(文佳佳地址欄中)
      2. 地址欄上面輸入 %appdata%
      3. 在這里建一個文件夾 pip
      4. 在pip文件夾里新建一個文件叫做pip.ini,內容如下寫即可
        • [global]
        • timeout = 6000
        • index-url = https://mirrors.aliyun.com/pypi/simple/
        • trusted-host = mirrors.aliyun.com
    3. linux中:
      1. cd ~
      2. mkdir ~/.pip
      3. vi ~/.pip/pip.conf
      4. 編輯內容,和windows一樣
    4. 需要安裝:pip install bs4
      • bs4在使用時候需要一個第三方的庫, 把這個庫也安裝一下
      • pip install lxml
  • 基礎使用
    1. 導包: from bs4 import BeautifulSoup
    2. 使用方式:可以將html文檔,轉化為BeautifulSoup對象,然后通過對象的方法 或者屬性去查找指定節點的內容
      1.  轉化本地文件: soup = BeautifulSoup(open("本地文件"), "lxml")
      2. 轉化網絡文件: soup = BeautifulSoup("字符串類型或者字節類型", "lxml")
      3. 打印soup對象顯示內容為htnl文件中的內容
  • BeautifulSoup知識點:
    1. 根據標簽名查找:
      • soup.a   只能查找第一符合要求的標簽
    2. 獲取屬性:
      • soup.a.attrs    獲取所有屬性和屬性值,返回一個字典
      • soup.a.attrs["href"]    獲取href屬性
      • soup.a["href"]    也可以簡寫成這種形式
    3. 獲取內容
      • soup.a.string
      • soup.a.text
      • soup.a.get_text()
      • 注意,如果標簽還有標簽,那么string獲取到的結果為None,而其他兩個,可以獲取文本內容
    4. find:找到第一個 符合要求的標簽
      • soup.find("a")   找到第一個符合要求的
      • soup.find("a", title="xuexue")
      • soup.find("a", alt="xuexue")
      • soup.find("a", class="xuexue")
      • soup.find("a", id="xuexue")
    5. find_all:找到所有符合 要求的標簽
      • soup.find_all("a")
      • soup.find_all(["a","b"])   # 找到所有的a標簽和b標簽
      • soup.find_all("a", limit=2)  # 限制前兩個
    6. 根據選擇器選擇指定的內容
      • select:soup.select("#feng")
      • 常見的選擇器:標准選擇器(a),類選擇器(.),id選擇器(#),層級選擇器
        • 層級選擇器:
          • div.xuexue #xiaoxue.haha .hehe   下面好多級
          • div>p>a>.xuexue   只能是下面一級
        • 注意:select選擇器返回的 永遠是列表,需要通過下標提取指定的對象

相關的代碼如下:

import requests
from bs4 import BeautifulSoup # 指定響應頭 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36" } # 定義解析內容的函數 def parse_content(url): # 獲取標題正文頁數據 page_text = requests.get(url=url, headers=headers).text # 實例化一個BeautifulSoup對象 soup = BeautifulSoup(page_text, "lxml") # 解析獲得標簽 element = soup.find("div", class_="chapter_content") content = element.text # 獲取標簽中的數據值 return content if __name__ == '__main__': url = "http://www.shicimingju.com/book/sanguoyanyi.html" # 發送請求后的響應體 response = requests.get(url=url, headers=headers) page_text = response.text print(page_text) # 創建soup對象 soup = BeautifulSoup(page_text, "lxml") # 解析數據 a_else = soup.select(".book-mulu>ul>li>a") print(a_else) cap = 1 for ele in a_else: print("開始下載di%s章節" % cap) cap += 1 title = ele.string content_url = "http://www.shicimingju.com" + ele["href"] content = parse_content(content_url) print(content) content = content.replace("\xa0", "") # 持久化存儲 with open("./mengsanguo.txt", "w") as fp: fp.write(title + ":" + content + "\n\n\n\n\n") print("結束下載第%s章節" % cap)

4,驗證碼的處理

 

  • 相關門戶網站進行登錄的時候,如果用戶連續登錄的次數超過3次或者5次的時候,就會在登錄頁面中生成驗證碼,通過驗證碼達到分流和反爬的效果
  • 雲打碼處理平台是一個很好的處理驗證碼的平台

雲打碼平台處理驗證碼實現流程:

 

  1. 對攜帶驗證碼的頁面數據進行爬取
  2. 可以將頁面數據中驗證碼進行解析,驗證碼圖片下載到本地
  3. 可以將 驗證碼圖片提交給第三方平台進行識別,返回驗證碼圖片上的數據值
    • 雲打碼平台:
      1. 在官網中注冊(普通用戶和開發者用戶)
      2. 登錄開發者用戶:
        1. 實例代碼的下載
        2. 創建一個軟件
      3. 使用實例代碼中的源碼文件中的代碼進行修改,讓其識別驗證碼圖片中的數據值
  4. 代碼展示:
# 該函數調用了打碼平台的相關的接口對指定的驗證碼圖片進行識別,返回圖片上的數據值
def getCode(codeImg):
    # 雲打碼普通用戶的用戶名
    username = "xueren"
    # 雲打碼平台普通用戶的密碼
    password = "xueren123"
    # 軟件ID,開發者分成必要參數,登錄開發者后台[我的軟件]獲得!
    # 軟件密鑰,開發者分成必要參數 ,登錄開發者后台[我的軟件]獲得!
    appkey = "4997f67b0128c77cda6db5259f5f76a9"
    # 驗證碼圖片文件
    filename = codeImg # 驗證碼類型, 列如:1004表示4位字母數字,不同類型收費不同,請准確 填寫,否則影響別率 查詢所有驗證碼類型:http://www.yundama.com/price.html codetype = 3000 # 超市時間,秒 timeout = 20 # 檢查 if (username == "username"): print("請設置好相關參數再測試") else: # 初始化 yundama = YDMHttp(username, password, appid, appkey) # 登錄雲打碼 uid = yundama.login() print("uid: %s" % uid) # 查詢余額 balance = yundama.balance() print("balance:"% balance) # 開始識別,圖片路徑, 驗證碼類型ID,超時時間(秒), 識別結果 cid, result = yundama.decode(filename, codetype, timeout) print("cod: %s, result: %s" % (cid, result)) return result

人人網驗證碼的爬取及處理:

def get_code_text(codeType, imgPath):
    # 用戶名:普通用戶
    username = "xueren"
    # 密碼
    password = "xueren123"
    # 軟件ID, 開發者分成必要參數.登錄開發者后台[我的軟件]獲得!
    appid = 6609
    # 軟件密鑰,開發者分成必要參數,登錄開發者后台[我的軟件]獲得!
    appkey = "4997f67b0128c77cda6db5259f5f76a9"
    # 圖片文件
    filename = imgPath # 驗證碼類型, # 列:1004表示4位字母數字,不同類型收費不同.請准確填寫,否則影響識別率. # 在此查詢所有類型 http://www.yundama.com/price.html codetype = codeType # 超時時間,秒 timeout = 10 # 檢查 if(username == "username"): print("請設置好相關參數在測試") else: yundama = YDMHttp(username, password, appid, appkey) # 登錄雲打碼 uid = yundama.login(); print("uid:%s" % uid) # 查詢余額 balance = yundama.balance(); print("balance %s" % balance) # 開始識別,圖片路徑,驗證碼類型ID, 超時時間(秒), 識別結果 cid, result = yundama.decode(filename, codeType, timeout); # print("cid: %s, result: %s" % (cid, result)) return result
import requests
from lxml import etree from urllib import request # 獲取一個session對象 session = requests.Session() # session對象和requests作用幾乎一樣,都可以進行請求的發送,並且請求發送的方式也是一樣的 # session進行請求的發送,如果會產生cookie的話 ,則cookie會自動被存儲到session中 # 獲取驗證碼圖片 # 找到請求的url url = "http://www.renren.com/" # 找到請求的請求頭UA headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36" } # 向人人網發送請求,拿到驗證碼 page_text = requests.get(url=url, headers=headers).text # 將驗證碼圖片解析出來進行持久化存儲 tree = etree.HTML(page_text) # 拿到驗證碼的url code_img_src = tree.xpath('//*[@id="verifyPic_login"]/@src')[0] code = None if code_img_src: # 保存驗證碼圖片 request.urlretrieve(url=code_img_src, filename="./code.jpg") # 調用damayun破解驗證碼 code = get_code_text(2004, "./code.jpg") print(code) # 模擬登陸 login_url = "http://www.renren.com/ajaxLogin/login?1=1&uniqueTimestamp=201903209693" data = { 'email': "18731229751", "icode": code, "origURL": "http://www.renren.com/home", "domain": "renren.com", "key_id":"1", "captcha_type": "web_login", "password": "2ffe7682a8e5f246b91115f02ed84bec462e9e81cb1d53c26159c422b2bf4b23", "rkey": "8903172b11d2f2476d3db75417116a1c", "f": "https%3A%2F%2Fwww.baidu.com%2Flink%3Furl%3D52HnJhxy_aSfPbj2R5LMlG4a6294qGfXen5puJr--HG%26wd%3D%26eqid%3D9e26635d000114c1000000035c35e61e", } # 進行登錄, 當登錄成功之后,可以獲取cookie # cookie會被保存到sessio中 response = session.post(url=login_url, headers=headers, data=data) # 對登錄成功后對應的當前用戶的個人詳情頁面進行請求發送 detail_url = "http://www.renren.com/969397800/profile" # 該次請求使用的是session對象,該請求已經攜帶了cookie page_text = session.get(url=detail_url, headers=headers).text # 保存到本地 with open("./renren.html", "w", encoding="utf-8") as fp: fp.write(page_text) print("ok")

 

打賞

免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號  © 2018-2021 CODEPRJ.COM