爬蟲之聚焦爬蟲與驗證碼處理


一 . 我們先安裝一個叫Anaconda的軟件

  參考鏈接: https://zhuanlan.zhihu.com/p/32925500  這里我們主要用到的是jupyter notebook,下載anaconda的原因是幫助解決jupyter的依賴關系

    然后在文件夾下按住shift+右鍵 ->在此處打開命令窗口,輸入jupyter notebook就可以了!

二 . 實現聚焦爬蟲(數據解析)

  編碼流程:

1.指定url 2.發起請求 3.獲取相應數據 4.數據解析 5.持久化存儲

  如何實現數據解析:

1.正則,(基本上不會用,這里不做介紹) 2.bs4 3.xpath

  數據解析的原理

1.實現標簽定位 2.將標簽中存儲的文本內容或者相關的屬性值進行提取

  bs4數據解析

# 環境安裝
    1.pip install bs4 2.pip install lxml # 使用方式:可以將一個html文檔,轉化為BeautifulSoup對象,然后通過對象的方法或者屬性去查找指定的節點內容
        (1)轉化本地文件: - soup = BeautifulSoup(open('本地文件'), 'lxml') (2)轉化網絡文件: page_text = requests.get(url, headers=headers).text soup = BeautifulSoup(page_text , 'lxml') (3)打印soup對象顯示內容為html文件中的內容 # 調用該對象中相關的屬性或者方法進行標簽的定位和內容的提取
    (1)根據標簽名查找 - soup.a 只能找到第一個符合要求的標簽 (2)獲取屬性 - soup.a.attrs 獲取a所有的屬性和屬性值,返回一個字典 - 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="xxx") - soup.find('a', alt="xxx") - soup.find('a', class_="xxx") - soup.find('a', id="xxx") (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 .dudu #lala .meme .xixi 下面好多級
                div > p > a > .la 只能是下面一級 div p div標簽所有的p標簽(子標簽) 【注意】select選擇器返回永遠是列表,需要通過下標提取指定的對象

  示例: 爬取三國演義的章節與內容

from bs4 import BeautifulSoup url = 'http://www.shicimingju.com/book/sanguoyanyi.html' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) \
    Chrome/70.0.3538.110 Safari/537.36
' } page_text = requests.get(url=url, headers=headers, verify=False).text # 實例化soup對象 soup = BeautifulSoup(page_text, 'lxml') # 解析出章節標題和詳情頁的鏈接 li_list = soup.select('.book-mulu > ul > li') # 持久化存儲 f = open('./sanguo.txt', 'w', encoding='utf-8') for li in li_list: title = li.a.string detail_url = 'http://www.shicimingju.com' + li.a['href'] # 對詳情頁url發起請求,進行章節內容的解析提取 detail_page_text = requests.get(url=detail_url, headers=headers, verify=False).text # 將詳情頁頁面內容解析提取 detail_soup = BeautifulSoup(detail_page_text, 'lxml') div_tag = detail_soup.find('div', class_='chapter_content') content = div_tag.text f.write(title + ':' + content + '\n') f.close()

  xpath解析(最常用)

  測試HTML頁面

<html lang="en">
<head>
    <meta charset="UTF-8" />
    <title>測試bs4</title>
</head>
<body>
    <div>
        <p>百里守約</p>
    </div>
    <div class="song">
        <p>李清照</p>
        <p>王安石</p>
        <p>蘇軾</p>
        <p>柳宗元</p>
        <a href="http://www.song.com/" title="趙匡胤" target="_self">
            <span>this is span</span> 宋朝是最強大的王朝,不是軍隊的強大,而是經濟很強大,國民都很有錢</a>
        <a href="" class="du">總為浮雲能蔽日,長安不見使人愁</a>
        <img src="http://www.baidu.com/meinv.jpg" alt="" />
    </div>
    <div class="tang">
        <ul>
            <li><a href="http://www.baidu.com" title="qing">清明時節雨紛紛,路上行人欲斷魂,借問酒家何處有,牧童遙指杏花村</a></li>
            <li><a href="http://www.163.com" title="qin">秦時明月漢時關,萬里長征人未還,但使龍城飛將在,不教胡馬度陰山</a></li>
            <li><a href="http://www.126.com" alt="qi">岐王宅里尋常見,崔九堂前幾度聞,正是江南好風景,落花時節又逢君</a></li>
            <li><a href="http://www.sina.com" class="du">杜甫</a></li>
            <li><a href="http://www.dudu.com" class="du">杜牧</a></li>
            <li><b>杜小月</b></li>
            <li><i>度蜜月</i></li>
            <li><a href="http://www.haha.com" id="feng">鳳凰台上鳳凰游,鳳去台空江自流,吳宮花草埋幽徑,晉代衣冠成古丘</a></li>
        </ul>
    </div>
</body>
</html>

  使用姿勢:

通用性比較強,不光python能用 環境安裝:pip install lxml 導包:from lxml import etree # 解析原理:
    1.實例化一個etree對象,且將解析的頁面源碼加載到該對象中 2.使用該對象中的xpath方法結合着xpath表達式進行標簽定位和數據解析提取   - 本地文件:tree = etree.parse(文件名) tree.xpath("xpath表達式") page_text = requests.get(url, headers=headers).text   - 網絡數據:tree = etree.HTML(page_text) tree.xpath("xpath表達式") # xpath表達式

/:從跟標簽開始實現層級定位  /html/body/div //:從任意位置實現標簽定位 屬性定位: #找到class屬性值為song的div標簽
    //div[@class="song"] 層級&索引定位: #找到class屬性值為tang的div的直系子標簽ul下的第二個子標簽li下的直系子標簽a
    //div[@class="tang"]/ul/li[2]/a 邏輯運算: #找到href屬性值為空且class屬性值為du的a標簽
    //a[@href="" and @class="du"] 模糊匹配: //div[contains(@class, "ng")] //div[starts-with(@class, "ta")] 取文本: # /表示獲取某個標簽下的文本內容
    # //表示獲取某個標簽下的文本內容和所有子標簽下的文本內容
    //div[@class="song"]/p[1]/text()  # 獲取第一個p標簽的文本
    //div[@class="tang"]//text()  # 獲取div下面的所有文本內容
取屬性: //div[@class="tang"]//li[2]/a/@href

  示例1:

import requests from lxml import etree url = 'http://pic.netbian.com/4kdongwu/' headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) \
    Chrome/70.0.3538.110 Safari/537.36
' } response = requests.get(url=url,headers=headers) # 手動設置相應數據的編碼 # response.encoding = 'utf-8' page_text = response.text tree = etree.HTML(page_text) li_list = tree.xpath('//div[@class="slist"]/ul/li') for li in li_list: img_src = li.xpath('./a/img/@src')[0] img_name = li.xpath('./a/b/text()')[0] img_name = img_name.encode('iso-8859-1').decode('gbk') # 解決中文亂碼問題 print(img_src,img_name)

  示例2:

# 爬高清壁紙圖片:http://pic.netbian.com/4kmeinv/

import requests from lxml import etree import time url = 'http://pic.netbian.com/4kmeinv/' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) \
  Chrome/70.0.3538.110 Safari/537.36
', } #獲取頁面文本數據 response = requests.get(url=url,headers=headers) page_text = response.text #解析頁面數據(獲取頁面中的圖片鏈接) #創建etree對象 tree = etree.HTML(page_text) li_list = tree.xpath('//div[@class="slist"]//li') #解析獲取圖片地址和圖片的名稱 for li in li_list: time.sleep(0.2) # 防止頻率太頻繁 image_url = li.xpath('.//img/@src') image_url_all = 'http://pic.netbian.com'+ image_url[0] image_name = li.xpath('.//b/text()')[0] image_name = image_name.encode('iso-8859-1').decode('gbk') url_name = image_url_all + ' :' + image_name print(url_name)

 

三 . 驗證碼處理

  引入:

相關的門戶網站在進行登錄的時候,如果用戶連續登錄的次數超過3次或者5次的時候,就會在登錄頁中動態生成驗證碼。通過驗證碼達到分流和反爬的效果。

  解決辦法:

使用雲打碼平台識別驗證碼

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

- 1.對攜帶驗證碼的頁面數據進行抓取 - 2.可以將頁面數據中驗證碼進行解析,驗證碼圖片下載到本地 - 3.可以將驗證碼圖片提交給三方平台進行識別,返回驗證碼圖片上的數據值 - 雲打碼平台: - 1.在官網中進行注冊(普通用戶和開發者用戶) - 2.登錄開發者用戶: - 1.實例代碼的下載(開發文檔-》調用實例及最新的DLL->PythonHTTP實例下載) - 2.創建一個軟件:我的軟件->添加新的軟件 -3.使用示例代碼中的源碼文件中的代碼進行修改,讓其識別驗證碼圖片中的數據值

  代碼展示:

# 該函數就調用了打碼平台的相關的接口對指定的驗證碼圖片進行識別,返回圖片上的數據值
def getCode(codeImg): # 雲打碼平台普通用戶的用戶名
    username    = 'attila666'

    # 雲打碼平台普通用戶的密碼
    password    = 'attila666'                            
    
    # 軟件ID,開發者分成必要參數。登錄開發者后台【我的軟件】獲得!
    appid       = 6003                                     

    # 軟件密鑰,開發者分成必要參數。登錄開發者后台【我的軟件】獲得!
    appkey      = '1f4b564483ae5c907a1d34f8e2f2776c'    

    # 驗證碼圖片文件
    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: %s' % balance) # 開始識別,圖片路徑,驗證碼類型ID,超時時間(秒),識別結果
        cid, result = yundama.decode(filename, codetype, timeout); print('cid: %s, result: %s' % (cid, result)) return result

 


免責聲明!

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



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