簡單爬取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()獲取所有的連結,然後多執行緒下載檔案。當下載完成後,程式結束。