使用requests獲取圖片並保存


獲取某一個網站的圖片信息需要用到requests模塊,所以我們需要安裝requests

安裝

pip install requests  # 直接安裝
pip install -i https://pypi.doubanio.com/simple/ requests  # 指定地址安裝

 

測試是否安裝成功

import requests   # 回車不報錯就算安裝成功
response = requests.get("https://www.baidu.com")
print(response.status_code)  # 200,證明訪問成功

網絡正常的情況下,可以訪問百度,證明安裝成功

 

發送請求

import requests  # 導包
response = requests.request(method='get', url='https://www.baidu.com')  # 向百度首頁發送請求,請求方式是get
print(response.status_code)  # 獲取返回code碼

request類中常用的參數:

  • method:請求方式。
  • url:請求URL。
  • **kwargs:
    • params:字典或者字節序列,作為參數增加到url中,使用這個參數可以把一些鍵值對以k1=v1&k2=v2的模式增加到url中,get請求中用的較多。
    • data:字典、字節序列或者文件對象,重點作為向服務器提供或提交資源,作為請求的請求體,與params不同放在url上不同。它也可以接受一個字符串對象。
    • json:json格式的數據,可以向服務器提交json類型的數據。
    • headers:字典,定義請求的請求頭,比如可以headers字典定義user agent。
    • cookies:字典或者CookieJar。
    • auth:元組,用來支持HTTP認證功能。
    • files:字典,用來向服務器傳輸文件。
    • timeout:指定超時時間。
    • proxies:字典,設置代理服務器。
    • allow_redirects:開關,是否允許對URL進行重定向,默認為True。
    • stream:開關,是否對獲取內容進行立即下載,默認為False,也就是立即下載。這里需要說明的,stream一般應用於流式請求,比如說下載大文件,不可能一次請求就把整個文件都下載了,不現實,這種情況下,就要設置stream=True,requests無法將連接釋放回連接池,除非下載完了所有數據,或者調用了response.close。
    • verify:開關,用於SSL證書認證,默認為True。
    • cert:用於設置保存本地SSL證書路徑。

獲取響應

當一個請求被發送后,會有一個response響應。requests同樣為這個response賦予了相關方法:

  • response:響應對象。
  • response.status_code:請求返回狀態碼。
  • response.text:字符串形式的響應內容。
  • response.json():返回響應的是json類型的數據,如果響應的類型不是json,則拋出ValueError
  • response.content:二進制的響應內容。
  • response.iter_content(chunk_size):生成器,在stream=True的情況下,當遍歷生成器時,以塊的形式返回,也就是一塊一塊的遍歷要下載的內容。避免了遇到大文件一次性的將內容讀取到內存中的弊端,如果stream=False,全部數據作為一個塊返回。chunk_size參數指定塊大小。
  • response.iter_lines():生成器,當stream=True時,迭代響應數據,每次一行,也就是一行一行的遍歷要下載的內容。同樣避免了大文件一次性寫入到內存中的問題。當然,該方法不安全。至於為啥不安全,咱也不知道,咱也不敢問,主要是官網上沒說!經查,如果多次調用該方法,iter_lines不保證重新進入時的安全性,因此可能會導致部分收到的數據丟失。
  • response.cookies:響應中的cookie信息。
  • response.cookies.get_dict():以字典的形式返回cookies信息。
  • response.cookies.items():以列表的形式返回cookies信息。
  • response.headers:響應頭字典。取其中的指定key,response.headers.get('Content-Type', '哎呀,沒取到!')
  • response.reqeust:請求類型。
  • response.url:請求的URL。
  • response.reason:響應HTTP狀態的文本原因。
  • response.encoding:響應結果的編碼方式。
  • response.encoding = “gbk”:修該響應編碼方式,比如說響應結果的編碼是utf-8,通過這么response.encoding = “gbk”指定為gbk。
  • response.apparent_encoding:根據響應字節流中去chardet庫中匹配,返回編碼方式,並不保證100%准確。
  • response.history:以列表的形式返回請求記錄。列表內的請求以最老到最新排序。

 

獲取7160網站的圖片:獲取當前頁面的圖片

'''
http://www.7160.com/meishitupian/list_15_2.html
pip install beautifulsoup4  # 需要先安裝此模塊

'''

# 0. 導包
import os
import requests
from bs4 import BeautifulSoup  # 不同於其他模塊,BeautifulSoup導入的時候不是直接import BeautifulSoup,直接導入會報錯

#  在代碼之前先定義全局常量
# os.path.abspath(__file__) 指當前文件的絕對路徑
# os.path.dirname() 指父級目錄的絕對路徑
# os.path.dirname(os.path.abspath(__file__)) 指以當前文件的絕對路徑找到父級目錄的絕對路徑
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

# 1. 模擬瀏覽器發請求
response = requests.get(url='http://www.7160.com/meishitupian/list_15_2.html')
# print(response.status_code)  # 查看是否請求成功
# print(response.encoding)  # 查看編碼類型
response.encoding = 'gbk'  # 獲取的文件信息是亂碼,需要轉碼,可以嘗試多種,直到正常顯示

# 2. 獲取字符串形式的請求內容,方便后續代碼中使用
text = response.text

# 3. 使用bs4庫解析請求,需要傳入需要解析的文件,指定解析器
soup = BeautifulSoup(text, 'html.parser')  # 需要解析的文件是text, 是文本類型的,所以使用html.parser:解析器,負責解析文本
# print(soup)  # 結果同text相同,拿到解析結果去分析和操作數據

# 從整個文本中進一步縮小定位范圍
# 查找name是div盒子,這個div中class的名字為news_bom-left的內容
# find方法中此類參數的固定寫法
div_obj = soup.find(name='div', attrs={"class": "news_bom-left"})

# 4. 定位圖片位置
li_list = div_obj.find_all(name="li")  # 從這個盒子中找所有li標簽

# 圖片要一張一張去處理並保存,所以要循環,
for li in li_list:
    # 5. 獲取圖片鏈接
    img = li.find(name='img')  # 查看這一條li中name是img的標簽
    src = img.get("src")  # 從這個標簽中獲取圖片的鏈接
    
    # 6. 使用requests模塊向圖片鏈接發請求
    res = requests.get(url=src)
    
    # 7. 保存圖片到本地
    # os.path.join 是拼接路徑,BASE_DIR指當前文件的父級目錄的絕對路徑
    # src.rsplit('/', 1)[-1] 是切割了圖片地址,使用切割后的字符串作為要保存的文件的名字,也可以用其他的字段進行處理作為文件名
    # 這一步實際就是給即將保存的文件安排一個路徑,這個路徑就是當前文件所處的父文件夾下的7160這個文件夾
    # 注意:'7160'這個文件夾要先創建好,不然會報錯
    file_path = os.path.join(BASE_DIR, '7160', src.rsplit('/', 1)[-1])
    with open(file_path, 'wb') as f:  # 圖片信息是二進制形式,所以要用wb寫入
        f.write(res.content)  # 將請求圖片獲取到的二進制響應內容寫入文件中
    # break  # 調試時候用,只獲取第一條信息,調試結束,注釋掉break,即可全部獲取到文件
使用requests和BeautifulSoup獲取圖片並保存到本地--一次性全部寫入

使用此種方法有個弊端,如果文件過大,可能會導致下載到本地之后,導致本地存儲空間不足,下載完畢之后會有部分文件丟失

如果是大文件或者多個文件,建議循環下載,如果存儲空間不足,之前的文件不會缺失

# stream默認情況下是false,會立即開始下載文件並存放到內存當中
# 當把stream的參數設置成True時,它不會立即開始下載,當你使用iter_content遍歷內容或訪問內容屬性時才開始下載
response = requests.get(url_file, stream=True)
with open("file_path", "wb") as f:
# iter_content:一塊一塊的遍歷要下載的內容,chunk_size是每一塊的字節數,結合使用可以防止占用過多的內存
# 循環下載文件,按照chunk_size設置的字節數,每次只下載這一大小的數據
    for i in response.iter_content(chunk_size=512):
            f.write(i)
使用iter_content方法按字節大小循環下載

 

獲取天極網的圖片:保存圖片時有多級文件夾

'''
http://pic.yesky.com/c/6_3655_5.shtml
需求:
將圖片上的文件按頁面的分類保存,一共兩級文件夾,保存的格式如下
               'tianji'                # 一級文件夾
                  '趙薇圖片'            # 二級文件夾
                      '趙薇圖片111'     # 具體圖片文件
                      '趙薇圖片222'
                      '趙薇圖片333'
                  '林心如圖片'
                  '李沁圖片'
'''
import os
import requests
from bs4 import BeautifulSoup

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
# 1、向指定連接發請求
response = requests.get(url='http://pic.yesky.com/c/6_3655_5.shtml')

# 2、使用bs4解析requests請求的響應文本
soup = BeautifulSoup(response.text, 'html.parser')   # 延伸可搜索lxml,學習python3解析庫lxml
div_obj = soup.find(name='div', attrs={"class": "lb_box"})
dd_list = div_obj.find_all(name='dd')

for dd in dd_list:
    # 獲取div中所有圖片所在a標簽的url
    a_url = dd.find(name='a').get('href')
    # 要先創建好'tianji'文件夾,再在此文件夾下創建N個二級文件夾用來存放圖片
    path = os.path.join(BASE_DIR, 'tianji', dd.find(name='a').text)
    if not os.path.isdir(path):  # 如果不存在這個二級文件夾,則創建,不加這一步可能會報錯
        os.mkdir(path)
    
    # 向url發請求
    a_response = requests.get(url=a_url)
    a_response.encoding = 'gbk'

    # 拿到url中的text文本
    a_text = a_response.text
    son_soup = BeautifulSoup(a_text, 'html.parser')  # lxml
    son_div_obj = son_soup.find(name='div', attrs={"id": "scroll"})
    
    for img in son_div_obj.find_all(name='img'):
        # 獲取圖片鏈接,並發請求
        son_src = img.get('src').replace('113x113', '740x-')  # 使用大圖的像素替換圖片鏈接中的小圖像素,達到獲取大圖的目的
        son_response = requests.get(url=son_src)
        
        # 打開文件寫入
        img_path = os.path.join(path, son_src.rsplit("/", 1)[-1])
        with open(img_path, 'wb') as f:
            f.write(son_response.content)
        break
    break
使用循環內部套循環獲取二級頁面的圖片,並分兩級文件夾保存

 

獲取汽車之家圖片: 多頁面多圖片獲取

順序獲取,不考慮時間,不考慮分頁,只獲取第一頁

1、 爬取汽車之家新聞頁第一頁

 

順序獲取前20頁,將獲取圖片的代碼封裝成了函數,需要獲取多少頁只需簡單修改參數就行

import os, time
import requests   # 模擬瀏覽器發請求
from bs4 import BeautifulSoup   # 解析請求結果,也就是去請求結果中,取數據

url = "https://www.autohome.com.cn/all/"
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

def spider(num):
    
    # 1. 使用requests模塊向指定地址發請求,獲取請求結果
    response = requests.get(url="https://www.autohome.com.cn/all/{}/#liststart".format(num))
    # 2. 轉碼
    response.encoding = "gbk"
    
    # 3. 使用bs4取數據,解析請求結果
    soup = BeautifulSoup(response.text, "html.parser")
    div_obj = soup.find(name='div', attrs={"id": "auto-channel-lazyload-article"})
    img_list = div_obj.find_all(name="img")
    
    for img in img_list:
        # 獲取圖片的url,因為源地址是不全的,我們要拼接
        img_url = "https:" + img.get("src")
        # 使用requests模塊向圖片地址發請求,獲取圖片數據,bytes
        img_response = requests.get(url=img_url)
        # 制作保存圖片的路徑
        file_path = os.path.join(BASE_DIR, '222', img_url.rsplit('/', 1)[-1])
        # 將bytes類型的數據保存到本地
        with open(file_path, 'wb') as f:
            f.write(img_response.content)
        print('{} 爬取完畢'.format(img_url))  # 下載時在控制台輸入信息提示


if __name__ == '__main__':
    start = time.time()  # 開始執行時 當前時間的時間戳
    for num in range(1, 20):  # 循環獲取1-20頁的圖片
        spider(num)  # 獲取當前頁的圖片信息
    print(time.time() - start)  # 結束時的時間戳-開始時間的時間戳,計算差即用時時長
順序獲取汽車之家新聞頁前20頁--封裝成了函數

 

通過線程池獲取,無順序,但是提高了效率,縮短了獲取時間

# 1、導包
from concurrent.futures import ThreadPoolExecutor  # 線程池

# 2、在代碼中需要使用的位置上方加這一行
# 表示線程開始,將需要使用線程池的代碼放進來
t = ThreadPoolExecutor(max_workers=10)  # max_workers表示線程數

# 3、在代碼中結束的位置下方加這一行
# 當代碼執行完,結束線程,不再往進加任務
t.shutdown()  

 

import os, time
import requests   # 模擬瀏覽器發請求
from bs4 import BeautifulSoup   # 解析請求結果,也就是去請求結果中,取數據
from concurrent.futures import ThreadPoolExecutor  # 線程池

BASE_DIR = os.path.dirname(os.path.abspath(__file__))


def spider(num):
    # 1. 使用requests模塊向指定地址發請求
    # response = requests.request(method='get', url=url)
    page_url = "https://www.autohome.com.cn/all/{}/#liststart".format(num)
    response = requests.get(url=page_url)
    # 2. 獲取請求結果
    # print(response.encoding)  # ISO-8859-1
    response.encoding = "gbk"
    # print(response.text)
    # 3. 使用bs4取數據,解析請求結果
    soup = BeautifulSoup(response.text, "html.parser")
    div_obj = soup.find(name='div', attrs={"id": "auto-channel-lazyload-article"})
    img_list = div_obj.find_all(name="img")

    for img in img_list:
        # 獲取圖片的url,因為源地址是不全的,我們要拼接
        img_url = "https:" + img.get("src")
        # 使用requests模塊向圖片地址發請求,獲取圖片數據,bytes
        img_response = requests.get(url=img_url)
        # 制作保存圖片的路徑
        file_path = os.path.join(BASE_DIR, '222', img_url.rsplit('/', 1)[-1])
        # 將bytes類型的數據保存到本地
        with open(file_path, 'wb') as f:
            f.write(img_response.content)
        print('正在爬取{} 頁 中的{}圖片 爬取完畢'.format(page_url, img_url))

if __name__ == '__main__':
    start = time.time()
    t = ThreadPoolExecutor(max_workers=10)  # 10個線程,每次10個線程去獲取數據,可提高效率
    for num in range(1, 20):
        t.submit(spider, num)
    t.shutdown()  # 線程結束。當循環結束,結束線程,不再往進加任務
    print(time.time() - start)

線程池獲取汽車之家新聞頁前20頁圖片--提高效率
線程池獲取汽車之家新聞頁前20頁圖片--提高效率

 

 

 

 

 

 

結束。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM