溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Python異步新聞爬蟲之網(wǎng)絡(luò)請求函數(shù)的優(yōu)化案例

發(fā)布時間:2020-11-03 11:00:37 來源:億速云 閱讀:143 作者:小新 欄目:編程語言

這篇文章主要介紹Python異步新聞爬蟲之網(wǎng)絡(luò)請求函數(shù)的優(yōu)化案例,文中介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們一定要看完!

前面我們實現(xiàn)了一個簡單的再也不能簡單的新聞爬蟲,這個爬蟲有很多槽點,估計大家也會鄙視這個爬蟲。上一節(jié)最后我們討論了這些槽點,現(xiàn)在我們就來去除這些槽點來完善我們的新聞爬蟲。

問題我們前面已經(jīng)描述清楚,解決的方法也有了,那就廢話不多講,代碼立刻上(Talk is cheap, show me the code!)。

downloader 的實現(xiàn)

import requests
import cchardet
import traceback


def downloader(url, timeout=10, headers=None, debug=False, binary=False):
    _headers = {
        'User-Agent': ('Mozilla/5.0 (compatible; MSIE 9.0; '
                       'Windows NT 6.1; Win64; x64; Trident/5.0)'),
    }
    redirected_url = url
    if headers:
        _headers = headers
    try:
        r = requests.get(url, headers=_headers, timeout=timeout)
        if binary:
            html = r.content
        else:
            encoding = cchardet.detect(r.content)['encoding']
            html = r.content.decode(encoding)
        status = r.status_code
        redirected_url = r.url
    except:
        if debug:
            traceback.print_exc()
        msg = 'failed download: {}'.format(url)
        print(msg)
        if binary:
            html = b''
        else:
            html = ''
        status = 0
    return status, html, redirected_url


if __name__ == '__main__':
    url = 'http://news.baidu.com/'
    s, html,lost_url_found_by_大大派 = downloader(url)
    print(s, len(html),lost_url_found_by_大大派)

這個downloader()函數(shù),內(nèi)置了默認的User-Agent模擬成一個IE9瀏覽器,同時接受調(diào)用者自定義的headers和timeout。使用cchardet來處理編碼問題,返回數(shù)據(jù)包括:

狀態(tài)碼:如果出現(xiàn)異常,設(shè)置為0

內(nèi)容: 默認返回str內(nèi)容。但是URL鏈接的是圖片等二進制內(nèi)容時,注意調(diào)用時要設(shè)binary=True

重定向URL: 有些URL會被重定向,最終頁面的url包含在響應(yīng)對象里面

新聞URL的清洗

我們先看看這兩個新聞網(wǎng)址:

http://xinwen.eastday.com/a/n181106070849091.html?qid=news.baidu.com
http://news.ifeng.com/a/20181106/60146589_0.shtml?_zbs_baidu_news

上面兩個帶?的網(wǎng)站來自百度新聞的首頁,這個問號?的作用就是告訴目標服務(wù)器,這個網(wǎng)址是從百度新聞鏈接過來的,是百度帶過來的流量。但是它們的表示方式不完全一樣,一個是qid=news.baidu.com, 一個是_zbs_baidu_news。這有可能是目標服務(wù)器要求的格式不同導(dǎo)致的,這個在目標服務(wù)器的后臺的瀏覽統(tǒng)計程序中可能用得到。

然后去掉問號?及其后面的字符,發(fā)現(xiàn)它們和不去掉指向的是相同的新聞網(wǎng)頁。

從字符串對比上看,有問號和沒問號是兩個不同的網(wǎng)址,但是它們又指向完全相同的新聞網(wǎng)頁,說明問號后面的參數(shù)對響應(yīng)內(nèi)容沒有任何影響。

正在抓取新聞的大量實踐后,我們發(fā)現(xiàn)了這樣的規(guī)律:

新聞類網(wǎng)址都做了大量SEO,它們把新聞網(wǎng)址都靜態(tài)化了,基本上都是以.html, .htm, .shtml等結(jié)尾,后面再加任何請求參數(shù)都無濟于事。

但是,還是會有些新聞網(wǎng)站以參數(shù)id的形式動態(tài)獲取新聞網(wǎng)頁。

那么我們抓取新聞時,就要利用這個規(guī)律,防止重復(fù)抓取。由此,我們實現(xiàn)一個清洗網(wǎng)址的函數(shù)。

g_bin_postfix = set([
    'exe', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx',
    'pdf',
    'jpg', 'png', 'bmp', 'jpeg', 'gif',
    'zip', 'rar', 'tar', 'bz2', '7z', 'gz',
    'flv', 'mp4', 'avi', 'wmv', 'mkv',
    'apk',
])

g_news_postfix = [
    '.html?', '.htm?', '.shtml?',
    '.shtm?',
]


def clean_url(url):
    # 1. 是否為合法的http url
    if not url.startswith('http'):
        return ''
    # 2. 去掉靜態(tài)化url后面的參數(shù)
    for np in g_news_postfix:
        p = url.find(np)
        if p > -1:
            p = url.find('?')
            url = url[:p]
            return url
    # 3. 不下載二進制類內(nèi)容的鏈接
    up = urlparse.urlparse(url)
    path = up.path
    if not path:
        path = '/'
    postfix = path.split('.')[-1].lower()
    if postfix in g_bin_postfix:
        return ''

    # 4. 去掉標識流量來源的參數(shù)
    # badquery = ['spm', 'utm_source', 'utm_source', 'utm_medium', 'utm_campaign']
    good_queries = []
    for query in up.query.split('&'):
        qv = query.split('=')
        if qv[0].startswith('spm') or qv[0].startswith('utm_'):
            continue
        if len(qv) == 1:
            continue
        good_queries.append(query)
    query = '&'.join(good_queries)
    url = urlparse.urlunparse((
        up.scheme,
        up.netloc,
        path,
        up.params,
        query,
        ''  #  crawler do not care fragment
    ))
    return url

清洗url的方法都在代碼的注釋里面了,這里面包含了兩類操作:

判斷是否合法url,非法的直接返回空字符串

去掉不必要的參數(shù),去掉靜態(tài)化url的參數(shù)

網(wǎng)絡(luò)爬蟲知識點

1. URL清洗

網(wǎng)絡(luò)請求開始之前,先把url清洗一遍,可以避免重復(fù)下載、無效下載(二進制內(nèi)容),節(jié)省服務(wù)器和網(wǎng)絡(luò)開銷。

2. cchardet 模塊

該模塊是chardet的升級版,功能和chardet完全一樣,用來檢測一個字符串的編碼。由于是用C和C++實現(xiàn)的,所以它的速度非常快,非常適合在爬蟲中用來判斷網(wǎng)頁的編碼。

切記,不要相信requests返回的encoding,自己判斷一下更放心。上一節(jié),我們已經(jīng)列舉了一個例子來證明requests對編碼識別的錯誤,如果忘了的話,可以再去回顧一下。

3. traceback 模塊

我們寫的爬蟲在運行過程中,會出現(xiàn)各種異常,而且有些異常是不可預(yù)期的,也不知道它會出現(xiàn)在什么地方,我們就需要用try來捕獲異常讓程序不中斷,但是我們又需要看看捕獲的異常是什么內(nèi)容,由此來改善我們的爬蟲。這個時候,就需要traceback模塊。

比如在downloader()函數(shù)里面我們用try捕獲了get()的異常,但是,異常也有可能是cchardet.detect()引起的,用traceback.print_exc()來輸出異常,有助于我們發(fā)現(xiàn)更多問題。

以上是Python異步新聞爬蟲之網(wǎng)絡(luò)請求函數(shù)的優(yōu)化案例的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI