1. 程式人生 > >簡單爬取github下載連結

簡單爬取github下載連結

這幾天在看《python3 網路爬蟲實戰》,裡面用到了tesseract和它對應的語言包,為了避免使用這個庫出錯,我就開始在github上下載對應的語言包,但是無論是使用瀏覽器,還是wget下載,都會在下載一大半的時候出錯,於是萌生了一個分開下載的念頭。轉念一想,自己手動根據連結下載比較簡單,但是麻煩,而且重複;而恰好正在學習爬蟲的相關知識,因此有了下面的程式碼。

本示例程式碼爬取了https://github.com/tesseract-ocr/tessdata這個網址的所有有效下載連結,之後下載所有連結,並放置在當前目錄下的save資料夾下。

示例程式碼採用python3,用到的主要是requests和pyquery;前者負責獲取原始碼,後者則是用來css解析。

下圖是我的成果:

總共1000多M,因為實驗室的網路一如既往地穩定地差,所以總是下載失敗。

首先大致說一下匯入的模組:

import requests
from pyquery import PyQuery as pq
from urllib.parse import urljoin
from multiprocessing.pool import Pool
import os

1.requests 負責模擬瀏覽器傳送請求,並獲得響應,然後從響應中獲得html文字。

2.pyquery 負責解析html文字,獲取有用的標籤中的文字或屬性。

3.urllib.parse 僅僅用到了urljoin這個函式,負責給連結新增協議或者是域名。

4.os 負責建立save資料夾,以及把下載的檔案儲存到save資料夾下。

5.multiprocessing 多執行緒。

base_url = 'https://github.com'

def get_items_from_url(url):
    ''' 
    從url中獲取html文字,解析後返回dict
    @param url 要解析的連結
    @return dict {'name' : '檔名', 'url' : '下載連結'}
    '''
    headers = { 
        'Host' : 'github.com',
        'User-Agent' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36',
    }   
    response = requests.get(url = url, headers = headers)
        
    #響應失敗,則直接返回
    if response.status_code != 200:
        print('網頁載入錯誤')
        return
    #開始解析標籤
    doc = pq(response.text)
    items = doc.find('tr.js-navigation-item').items()

    for item in items:
        a = item.find('.content span a')
        name = a.text()
            
        #排除不必要的連結
        if name.find('traineddata') == -1: 
            continue
        yield {
            'name' : name,
            'url' : urljoin(base_url, a.attr('href').replace('blob', 'raw'))
        }

get_items_from_url()用來解析連結對應的html文字,獲取有用的資訊,在本示例下為檔名稱和對應的下載連結。

注意requests.get()中添加了一個請求頭,這個一般是用來模擬瀏覽器的;獲取響應後判斷了狀態碼即status_code是否為200(成功),不成功則直接退出;最後urljoin()函式則是給一些不存在協議或域名的連結加上缺失的部分。

def download_file(dic):
    ''' 
    下載檔案
    @param dic {'name' : '檔名', 'url' : '連結'}
    '''
    name = dic['name']
    url = dic['url']
    
    #保證save資料夾存在
    if not os.path.exists('save'):
        os.path.mkdir('save')

    print('Ready download %s' % name)
    #開始下載
    try:
        response = requests.get(url)
        file_path = 'save/{0}'.format(name)

        if not os.path.exists(file_path):
            with open(file_path, 'wb') as f:
                f.write(response.content)
            print('Successfully download %s' % name)
        else:
            print('%s already downloaded' % name)
    except requests.ConnectionError:
        print('Failed download %s' % name)

在download_file()函式中,通過呼叫requests.get()來下載檔案。

另外注意這裡用的是response.content而不是response.text   注:text獲取的是字串,而content則是位元組流

最後則是對上面兩個函式的呼叫了。

if __name__ == '__main__':
    #要下載的連結
    url = 'https://github.com/tesseract-ocr/tessdata'
    #解析完成的項列表
    groups = []
    
    for item in get_items_from_url(url):
        groups.append(item)
    print('parse data success!!!')
        
    #多執行緒下載
    pool = Pool()
    pool.map(download_file, groups)
    pool.close()
    pool.join()

這部分則比較簡單,先通過get_items_from_url()獲取所有的連結,然後多執行緒下載檔案。當下載完成後,程式結束。