Python3爬蟲下載pdf(二)

Python3爬蟲下載pdf(二)

最近在學習python的爬蟲,而且玩的不亦說乎,所以寫個博客,記錄並分享一下。html

需下載下載如下模塊python

  • bs4模塊
  • requests模塊

1、源碼

from concurrent.futures import ThreadPoolExecutor
import requests,argparse,re,os
from bs4 import BeautifulSoup as Soup

headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:54.0) Gecko/20100101 Firefox/54.0'
    }
    
## 設置命令行參數
def setArgs():
    parser = argparse.ArgumentParser(description="功能:下載pdf")
    parser.add_argument("url",help="目標url")
    parser.add_argument("-t","--thread",help="最大的線程數。默認爲3",default=3,type=int)
    parser.add_argument("-f","--filedir",help="文件保存的路徑.默認爲當前目錄下的downloads文件夾.若是不存在,便自動新建",default="downloads")
    return parser.parse_args()
    
## 獲取全部pdf的url
def getPdfUrl(root_url):
    response = requests.get(root_url, headers=headers)
    ## 若是requests沒有從頁面中得到字符編碼,那麼設置爲utf-8
    if "charset" not in response.headers:
        response.encoding = "utf-8"
    bsObj = Soup(response.text, "html.parser")
    pdfs = bsObj.find_all("a", {"href": re.compile(r'.pdf$')})
    ## 得到一個字典,key爲pdf完整url,value爲pdf名稱
    url_pdfName = {root_url[:root_url.rfind("/")+1]+pdf["href"]:pdf.string for pdf in pdfs}
    return url_pdfName

## 顯示正在下載的pdf的名稱
def showPdf(pdf_name):
    print(pdf_name+"...")

## 下載pdf
def savePdf(url,pdf_name):
    response = requests.get(url,headers=headers,stream=True)
    ## 若是指定的文件夾,那麼便新建
    if not os.path.exists(FILE_DIR):
        os.makedirs(FILE_DIR)
    ## os.path.join(a,b..)若是a字符串沒有以/結尾,那麼自動加上\\。(windows下)
    with open(os.path.join(FILE_DIR,pdf_name),"wb") as pdf_file:
        for content in response.iter_content():
            pdf_file.write(content)

## 設置要下載一個pdf要作的事情,做爲線程的基本
def downOne(url,pdf_name):
    showPdf(pdf_name)
    savePdf(url,pdf_name)
    print(pdf_name+" has been downloaded!!")
    
## 開始線程
def downPdf(root_url,max_thread):
    url_pdfName = getPdfUrl(root_url)
    with ThreadPoolExecutor(max_thread) as executor:
        executor.map(downOne,url_pdfName.keys(),url_pdfName.values())

def main():
    ## 得到參數
    args = setArgs()
    ## 若是沒有輸入必須的參數,便結束,返回簡略幫助
    try:
        global FILE_DIR
        FILE_DIR = args.filedir
        downPdf(args.url,args.thread)
    except:
        exit()

if __name__ == "__main__":
    main()

效果圖

圖片描述
圖片描述

例子:
圖片描述windows

備註

with ThreadPoolExecutor(max_thread) as executor:
     executor.map(downOne,url_pdfName.keys(),url_pdfName.values())
  • 使用工做的線程實例化ThreadPoolExecutor 類;executor._exit_ 方法會調用executor.shutdown(wait=True) 方法,它會在全部線程都執行完畢前阻塞線程。
  • map方法的做用與內置map函數相似,不過downOne函數會在多個線程中併發調用;map方法返回一個生成器。
global FILE_DIR
FILE_DIR = args.filedir
  • 設置了全局參數,用來接收文件路徑的值
  • 由於後面用executor.map() 傳參的時候,參數必須是iterabe,不知道咋放了,因此就設了個全局變量
相關文章
相關標籤/搜索