【網絡爬蟲學習】實戰,爬取網頁以及貼吧數據


實戰一

抓取您想要的網頁,並將其保存至本地計算機。

首先我們對要編寫的爬蟲程序進行簡單地分析,該程序可分為以下三個部分:

  • 拼接 url 地址
  • 發送請求
  • 將照片保存至本地

明確邏輯后,我們就可以正式編寫爬蟲程序了。

導入所需模塊

from urllib import request, parse

拼接 URL 地址

定義 URL 變量,拼接 url 地址。代碼如下所示:

url = 'http://www.baidu.com/s?wd={}'

word = input('請輸入想要搜索的內容:')
params = parse.quote(word)
full_url = url.format(params)

向URL發送請求

發送請求主要分為以下幾個步驟:

  • 創建請求對象-Request
  • 獲取響應對象-urlopen
  • 獲取響應內容-read

代碼如下所示:

# 重構請求頭
headers = {
    'User-Agent':
    'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'
}
# 創建請求對應
req = request.Request(url=full_url, headers=headers)
# 獲取響應對象
res = request.urlopen(req)
# 獲取響應內容
html = res.read().decode('utf-8')

保存為本地文件

把爬取的照片保存至本地,此處需要使用 Python 編程的文件 IO 操作,代碼如下:

filename = word + '.html'
with open(filename, 'w', encoding='utf-8') as f:
    f.write(html)

完整程序如下所示:

from urllib import request, parse
# 1.拼url地址
url = 'http://www.baidu.com/s?wd={}'

word = input('請輸入想要搜索的內容:')
params = parse.quote(word)
full_url = url.format(params)
# 2.發請求保存到本地
# 重構請求頭
headers = {
    'User-Agent':
    'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'
}
# 創建請求對應
req = request.Request(url=full_url, headers=headers)
# 獲取響應對象
res = request.urlopen(req)
# 獲取響應內容
html = res.read().decode('utf-8')
# 3.保存文件至當前目錄
filename = word + '.html'
with open(filename, 'w', encoding='utf-8') as f:
    f.write(html)

嘗試運行程序,並輸入 RioTianの博客園,確認搜索,然后您會在當前的工作目錄中找到“RioTianの博客園.html”文件。

函數式編程修改程序

Python 函數式編程可以讓程序的思路更加清晰、易懂。接下來,使用函數編程的思想更改上面代碼。

定義相應的函數,通過調用函數來執行爬蟲程序。修改后的代碼如下所示:

from urllib import request, parse


# 拼接URL地址
def get_url(word):
    url = 'http://www.baidu.com/s?{}'
    # 此處使用urlencode()進行編碼
    params = parse.urlencode({'wd': word})
    url = url.format(params)
    return url


# 發請求,保存本地文件
def request_url(url, filename):
    headers = {
        'User-Agent':
        'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:6.0) Gecko/20100101 Firefox/6.0'
    }
    # 請求對象 + 響應對象 + 提取內容
    req = request.Request(url=url, headers=headers)
    res = request.urlopen(req)
    html = res.read().decode('utf-8')
    # 保存文件至本地
    with open(filename, 'w', encoding='utf-8') as f:
        f.write(html)


# 主程序入口
if __name__ == '__main__':
    word = input('請輸入搜索內容:')
    url = get_url(word)
    filename = word + '.html'
    request_url(url, filename)

除了使用函數式編程外,也可以使用面向對象的編程方法(實戰二),在后續內容中會做相應介紹。

實戰二

抓取百度貼吧(https://tieba.baidu.com/)頁面,比如 Python爬蟲吧、編程吧,只抓取貼吧的前 5 個頁面即可。

判斷頁面類型

通過簡單的分析可以得知,待抓取的百度貼吧頁面屬於靜態網頁,分析方法非常簡單:打開百度貼吧,搜索“Python爬蟲”,在出現的頁面中復制任意一段信息,比如“爬蟲需要 http 代理的原因”,然后點擊右鍵選擇查看源碼,並使用 Ctrl+F 快捷鍵在源碼頁面搜索剛剛復制的數據,如下所示:

靜態網頁判斷

由上圖可知,頁面內的所有信息都包含在源碼頁中,數據並不需要從數據庫另行加載,因此該頁面屬於靜態頁面。

尋找URL變化規律

接下來尋找要爬取頁面的 URL 規律,搜索“Python爬蟲”后,此時貼吧第一頁的的 url 如下所示:

https://tieba.baidu.com/f?ie=utf-8&kw=python爬蟲&fr=search

點擊第二頁,其 url 信息如下:

https://tieba.baidu.com/f?kw=python爬蟲&ie=utf-8&pn=50

點擊第三頁,url 信息如下:

https://tieba.baidu.com/f?kw=python爬蟲&ie=utf-8&pn=100

重新點擊第一頁,url 信息如下:

https://tieba.baidu.com/f?kw=python爬蟲&ie=utf-8&pn=0

如果還不確定,您可以繼續多瀏覽幾頁。最后您發現 url 具有兩個查詢參數,分別是 kw 和 pn,並且 pn 參數具有規律性,如下所示:

第n頁:pn=(n-1)*50

#參數params
pn=(page-1)*50
params={
         'kw':name,
         'pn':str(pn)
        }

url 地址可以簡寫為:

https://tieba.baidu.com/f?kw=python爬蟲&pn=450

編寫爬蟲程序

下面以類的形式編寫爬蟲程序,並在類下編寫不同的功能函數,代碼如下所示:

from urllib import request,parse
import time
import random
from ua_info import ua_list #使用自定義的ua池

#定義一個爬蟲類
class TiebaSpider(object):
    #初始化url屬性
    def __init__(self):
        self.url='http://tieba.baidu.com/f?{}'

    # 1.請求函數,得到頁面,傳統三步
    def get_html(self,url):
        req=request.Request(url=url,headers={'User-Agent':random.choice(ua_list)})
        res=request.urlopen(req)
        #windows會存在亂碼問題,需要使用 gbk解碼,並使用ignore忽略不能處理的字節
        #linux不會存在上述問題,可以直接使用decode('utf-8')解碼
        html=res.read().decode("gbk","ignore")
        return html
    # 2.解析函數,此處代碼暫時省略,還沒介紹解析模塊
    def parse_html(self):
        pass
    # 3.保存文件函數
    def save_html(self,filename,html):
        with open(filename,'w') as f:
            f.write(html)
    # 4.入口函數
    def run(self):
        name=input('輸入貼吧名:')
        begin=int(input('輸入起始頁:'))
        stop=int(input('輸入終止頁:'))
        # +1 操作保證能夠取到整數
        for page in range(begin,stop+1):
            pn=(page-1)*50
            params={
                'kw':name,
                'pn':str(pn)
            }
            #拼接URL地址   
            params=parse.urlencode(params)
            url=self.url.format(params)
            #發請求
            html=self.get_html(url)
            #定義路徑
            filename='{}-{}頁.html'.format(name,page)
            self.save_html(filename,html)
            #提示
            print('第%d頁抓取成功'%page)
            #每爬取一個頁面隨機休眠1-2秒鍾的時間
            time.sleep(random.randint(1,2))
#以腳本的形式啟動爬蟲
if __name__=='__main__': 
    start=time.time()
    spider=TiebaSpider() #實例化一個對象spider
    spider.run() #調用入口函數
    end=time.time()
    #查看程序執行時間
    print('執行時間:%.2f'%(end-start))  #爬蟲執行時間

程序執行后,爬取的文件將會保存至 Pycharm 當前工作目錄,輸出結果:

輸入貼吧名:python爬蟲
輸入起始頁:1
輸入終止頁:2
第1頁抓取成功
第2頁抓取成功
執行時間:12.25

以面向對象方法編寫爬蟲程序時,思路簡單、邏輯清楚,非常容易理解,上述代碼主要包含了四個功能函數,它們分別負責了不同的功能,總結如下:

1) 請求函數

請求函數最終的結果是返回一個 HTML 對象,以方便后續的函數調用它。

2) 解析函數

解析函數用來解析 HTML 頁面,常用的解析模塊有正則解析模塊、bs4 解析模塊。通過分析頁面,提取出所需的數據,在后續內容會做詳細介紹。

3) 保存數據函數

該函數負責將抓取下來的數據保至數據庫中,比如 MySQL、MongoDB 等,或者將其保存為文件格式,比如 csv、txt、excel 等。

4) 入口函數

入口函數充當整個爬蟲程序的橋梁,通過調用不同的功能函數,實現數據的最終抓取。入口函數的主要任務是組織數據,比如要搜索的貼吧名、編碼 url 參數、拼接 url 地址、定義文件保存路徑。

爬蟲程序結構

用面向對象的方法編寫爬蟲程序時,邏輯結構較為固定,總結如下:

# 程序結構
class xxxSpider(object):
    def __init__(self):
        # 定義常用變量,比如url或計數變量等
       
    def get_html(self):
        # 獲取響應內容函數,使用隨機User-Agent
   
    def parse_html(self):
        # 使用正則表達式來解析頁面,提取數據
   
    def write_html(self):
        # 將提取的數據按要求保存,csv、MySQL數據庫等
       
    def run(self):
        # 主函數,用來控制整體邏輯
       
if __name__ == '__main__':
    # 程序開始運行時間
    spider = xxxSpider()
    spider.run()

注意:掌握以上編程邏輯有助於您后續的學習。

爬蟲程序隨機休眠

在入口函數代碼中,包含了以下代碼:

# 每爬取一個頁面隨機休眠1-2秒鍾的時間
time.sleep(random.randint(1,2))

爬蟲程序訪問網站會非常快,這與正常人類的點擊行為非常不符。因此,通過隨機休眠可以使爬蟲程序模仿成人類的樣子點擊網站,從而讓網站不易察覺是爬蟲訪問網站,但這樣做的代價就是影響程序的執行效率。

聚焦爬蟲是一種執行效率較低的程序,提升其性能,是業界一直關注的問題,由此也誕生了效率較高的 Python 爬蟲框架 Scrapy。


免責聲明!

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



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