Python網絡爬蟲(高性能異步爬蟲實例-aiohttp應用)


一、aiohttp與asynic異步爬蟲實例(站長素材)

  需求:爬取站長素材圖片,url:http://sc.chinaz.com/tupian/dahaitupian.html

from uuid import uuid4
import aiohttp
import asyncio
import lxml
import requests
from bs4 import BeautifulSoup

url = "http://sc.chinaz.com/tupian/meinvtupian_%d.html"

# 設置請求頭信息
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36'

}


# 生成soup對象
def get_soup(page_text):
    # 生成soup對象
    soup = BeautifulSoup(page_text, "lxml")
    return soup


# 獲取圖片詳細地址
imgs = []
def get_img_url(page_text):
    soup = get_soup(page_text)
    # 獲取所有的div標簽
    div_list = soup.select("#container div")
    for div in div_list:
        # 獲取到所有圖片的url
        img_src = div.find("img")["src2"]

        imgs.append(img_src)

    return imgs


# 回調函數 保存圖片
def url_parse(task):
    img_data = task.result()
    filename = f"{uuid4()}.jpg"
    print("正在下載圖片:", filename)
    file_path = "./img/"+filename
    # 寫入文件
    with open(file_path, "wb") as fp:
        fp.write(img_data)


# 創建一個特殊函數 async
async def get_request(url):
    # 創建一個aiohttp連接
    async with aiohttp.ClientSession() as cs:
        # 通過異步發送get請求 多任務掛起(await)
        async with await cs.get(url) as response:
            # 返回圖片Bytes 字節流
            return await response.read()


# 爬取圖片地址的url列表
urls = []
# 控制頁面數量,在異步寫入圖片文件,asynic有IO限制,太多IO操作會報錯
for page in range(1, 3):
    if page == 1:
        new_url = "http://sc.chinaz.com/tupian/dahaitupian.html"
    else:
        new_url = format(url % page)

    response = requests.get(new_url, headers=headers)
    response.encoding = "utf-8"
    page_text = response.text
    imgs = get_img_url(page_text)
    urls.append(imgs)


# 循環獲取網頁詳情頁
tasks = []
for fir_url in urls:
    for sec_url in fir_url:
        # 返回一個協程對象
        c = get_request(sec_url)
        # 通過返回的協程對象進一步封裝成一個任務對象
        task = asyncio.ensure_future(c)
        # 任務回調函數
        task.add_done_callback(url_parse)
        tasks.append(task)


# 創建事件循環對象
loop = asyncio.get_event_loop()
# 加載任務列表到事件循環,掛起並啟動事件循環
loop.run_until_complete(asyncio.wait(tasks))

二、asynic異步爬取錯誤處理

  

  錯誤原因:

  因為asyncio內部用到了select,而select就是系統打開文件數是有限度的,,這個其實是操作系統的限制,linux打開文件的最大數默認是1024,windows默認是509,超過了這個值,程序就開始報錯,
代碼一次性將處理url的函數作為任務扔進了一個超大的List中,這就引起了錯誤。
  錯誤處理:

  限制並發量,每次爬取不超過509的並發即可。

 

  


免責聲明!

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



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