??近段時(shí)間,筆者發(fā)現(xiàn)一個(gè)神奇的網(wǎng)站:http://www.allitebooks.com/ 锯茄,該網(wǎng)站提供了大量免費(fèi)的編程方面的電子書茶没,是技術(shù)愛好者們的福音晚碾。其頁面如下:
??那么我們是否可以通過Python來制作爬蟲來幫助我們實(shí)現(xiàn)自動(dòng)下載這些電子書呢格嘁?答案是yes.
??筆者在空閑時(shí)間寫了一個(gè)爬蟲,主要利用urllib.request.urlretrieve()函數(shù)和多線程來下載這些電子書讥蔽。
??首先呢,筆者的想法是先將這些電子書的下載鏈接網(wǎng)址儲存到本地的txt文件中新症,便于永久使用响禽。其Python代碼(Ebooks_spider.py)如下, 該代碼僅下載第一頁的10本電子書作為示例:
# -*- coding:utf-8 -*-
# 本爬蟲用來下載http://www.allitebooks.com/中的電子書
# 本爬蟲將需要下載的書的鏈接寫入txt文件隆嗅,便于永久使用
# 網(wǎng)站http://www.allitebooks.com/提供編程方面的電子書
# 導(dǎo)入必要的模塊
import urllib.request
from bs4 import BeautifulSoup
# 獲取網(wǎng)頁的源代碼
def get_content(url):
html = urllib.request.urlopen(url)
content = html.read().decode('utf-8')
html.close()
return content
# 將762個(gè)網(wǎng)頁的網(wǎng)址儲存在list中
base_url = 'http://www.allitebooks.com/'
urls = [base_url]
for i in range(2, 762):
urls.append(base_url + 'page/%d/' % i)
# 電子書列表侯繁,每一個(gè)元素儲存每本書的下載地址和書名
book_list =[]
# 控制urls的數(shù)量,避免書下載過多導(dǎo)致空間不夠!!!
# 本例只下載前3頁的電子書作為演示
# 讀者可以通過修改url[:3]中的數(shù)字,爬取自己想要的網(wǎng)頁書,最大值為762
for url in urls[:1]:
try:
# 獲取每一頁書的鏈接
content = get_content(url)
soup = BeautifulSoup(content, 'lxml')
book_links = soup.find_all('div', class_="entry-thumbnail hover-thumb")
book_links = [item('a')[0]['href'] for item in book_links]
print('\nGet page %d successfully!' % (urls.index(url) + 1))
except Exception:
book_links = []
print('\nGet page %d failed!' % (urls.index(url) + 1))
# 如果每一頁書的鏈接獲取成功
if len(book_links):
for book_link in book_links:
# 下載每一頁中的電子書
try:
content = get_content(book_link)
soup = BeautifulSoup(content, 'lxml')
# 獲取每本書的下載網(wǎng)址
link = soup.find('span', class_='download-links')
book_url = link('a')[0]['href']
# 如果書的下載鏈接獲取成功
if book_url:
# 獲取書名
book_name = book_url.split('/')[-1]
print('Getting book: %s' % book_name)
book_list.append(book_url)
except Exception as e:
print('Get page %d Book %d failed'
% (urls.index(url) + 1, book_links.index(book_link)))
# 文件夾
directory = 'E:\\Ebooks\\'
# 將書名和鏈接寫入txt文件中丽焊,便于永久使用
with open(directory+'book.txt', 'w') as f:
for item in book_list:
f.write(str(item)+'\n')
print('寫入txt文件完畢!')
可以看到咕别,上述代碼主要爬取的是靜態(tài)頁面,因此效率非常高雌贱!運(yùn)行該程序偿短,顯示結(jié)果如下:
在book.txt文件中儲存了這10本電子書的下載地址,如下:
??接著我們再讀取這些下載鏈接导街,用urllib.request.urlretrieve()函數(shù)和多線程來下載這些電子書纤子。其Python代碼(download_ebook.py)如下:
# -*- coding:utf-8 -*-
# 本爬蟲讀取已寫入txt文件中的電子書的鏈接,并用多線程下載
import time
from concurrent.futures import ThreadPoolExecutor, wait, ALL_COMPLETED
import urllib.request
# 利用urllib.request.urlretrieve()下載PDF文件
def download(url):
# 書名
book_name = 'E:\\Ebooks\\'+url.split('/')[-1]
print('Downloading book: %s'%book_name) # 開始下載
urllib.request.urlretrieve(url, book_name)
print('Finish downloading book: %s'%book_name) #完成下載
def main():
start_time = time.time() # 開始時(shí)間
file_path = 'E:\\Ebooks\\book.txt' # txt文件路徑
# 讀取txt文件內(nèi)容泽论,即電子書的鏈接
with open(file_path, 'r') as f:
urls = f.readlines()
urls = [_.strip() for _ in urls]
# 利用Python的多線程進(jìn)行電子書下載
# 多線程完成后卡乾,進(jìn)入后面的操作
executor = ThreadPoolExecutor(len(urls))
future_tasks = [executor.submit(download, url) for url in urls]
wait(future_tasks, return_when=ALL_COMPLETED)
# 統(tǒng)計(jì)所用時(shí)間
end_time = time.time()
print('Total cost time:%s'%(end_time - start_time))
main()
運(yùn)行上述代碼,結(jié)果如下:
再去文件夾中查看文件:
可以看到這10本書都已成功下載,總共用時(shí)327秒误堡,每本書的平均下載時(shí)間為32.7,約半分鐘陪踩,而這些書的大小為87.7MB,可見效率相當(dāng)高的肩狂!
??怎么樣姥饰,看到爬蟲能做這些多有意思的事情,不知此刻的你有沒有心動(dòng)呢列粪?心動(dòng)不如行動(dòng),至理名言~~
??本次代碼已上傳github, 地址為: https://github.com/percent4/Examples-of-Python-Spiders .
注意:本人現(xiàn)已開通兩個(gè)微信公眾號: 用Python做數(shù)學(xué)(微信號為:python_math)以及輕松學(xué)會Python爬蟲(微信號為:easy_web_scrape)力图, 歡迎大家關(guān)注哦~~