亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

Python爬蟲初體驗(2):多線程的應用及爬取中的實際問題

系統 2140 0

前情提要:Python爬蟲初體驗(1):利用requests和bs4提取網站漫畫

前幾天有些放松懈怠,并沒有做多少事情……這幾天要加油了!7月的計劃要抓緊時間完成!

今天瘋狂肝這個程序,算是暑假睡得最晚的一天了……(不過程序仍然有問題)


好的廢話不多說,進入正題

總結了下上次的爬蟲體驗。雖然能保證穩定下載,但是下載 50 張XKCD漫畫花費的時間達到了將近 10 分鐘,效率比較低。

所以這次學習了多線程,以求達到較快下載完全部 2000 余張漫畫的目標。 (另外配合 V 姓網絡加速工具保證連接外網的質量)

額外加入了 threading 模塊來實現多線程。

另外,改進了一下代碼風格,變量名稱


threading 庫中,Thread()?是進行多線程操作的關鍵。

在這里簡單的應用:threading.Thread(target=xxxx, args=(), kwargs=None)

(target 指向函數本身,args 為向目標函數傳遞的常規參數,kwargs 為傳遞的關鍵字參數)

然后!

一樣的方法去弄就可以了……

……

其實并不行。必須要把提取—解析—下載—存儲的全過程函數化,這樣才能實現多線程。

于是索性把所有過程都寫成了函數里……看起來雖然增加了代碼量,但是用起來就會很方便。

這里出現了一個問題:我開了?5 個線程,假如圖片一共有 2000 張還行,有 2003?張怎么辦?

emm,前 4 個線程下載 401 張圖,第 5 個下載 399 張圖就可以啦!

但是,如果前 400 張圖比較小,第 401-800 張圖比較大,這樣的話第一個線程結束時間遠早于第二個,如何解決?

其實可以挨個下載:不預先分配每個線程下載哪些圖片,直接
……

吐槽:居然花了我 8?個小時來搞這段代碼!沒想到這部分是這么難弄,

搞的來和當年學 OI 時有一樣的心情了。 (心情簡單.jpg)

不得不說,學 OI 的時候調試代碼的過程,和現在很類似。只是這里涉及更多的是實際操作而非算法。

實際操作就要考慮異常,異常處理,維護,等等。所以花時間也是避免不了的啦……

然后就可以繼續等待它慢慢扒圖……

……

……

然后就發現了一堆莫名其妙的錯誤!嗚嗚嗚……

Python爬蟲初體驗(2):多線程的應用及爬取中的實際問題_第1張圖片 Python爬蟲初體驗(2):多線程的應用及爬取中的實際問題_第2張圖片

(一共下載了 607 張圖片,最后 5 個線程全部斷掉了……為什么我設置了超時重試都還會 Timeout Error……QAQ)

(最好笑的還是 retry 4 in 3 times……這個是如何做到的)


再來。

后來發現,拋出異常時,僅僅針對?Readtime Error 的異常來解決問題。還有 Connection Error 等沒有處理。這個是最主要的問題。

某些地方寫入文件會有異常?嗯,這個暫時不了解原因。好像是圖片的鏈接讀取錯誤?

于是加入了兩種連網的錯誤處理。

為了防止連網出錯,特意把重試次數設為了 4 次,超時 Timeout 設為了 4 秒。

……

然而還是出錯了!

Python爬蟲初體驗(2):多線程的應用及爬取中的實際問題_第3張圖片

這次總算是查到了失敗的原因。

XKCD漫畫還真的有些不同尋常,例如:第 404 張漫畫竟然……就是一個 404 not found 的網站???

第 1350,2067 張漫畫居然有用戶交互的方式?

怪說不得線程又終止在這里了……

先把它們記下來,晚些時候再去解決吧。

發一個 不規范的 源碼存檔:

            
              #! python3
# Upgraded version. Use Threading to speed-up the download process.

import os,requests,bs4,threading,math,time
url = "http://xkcd.com/"
errList = []
mutex = threading.Lock()

def createDir():
    os.chdir("G:\\work\\gjmtest")
    os.makedirs(".\\comicsplus2", exist_ok=True)
    os.chdir(".\\comicsplus2")

def getResource(link,num=None,notify=False,tle=4):                       # default timeout: 3 seconds
    count = 1
    while count <= 4:
        try:
            if num is None:
                res = requests.get(link, timeout=tle)
            else:
                res = requests.get(link+str(num), timeout=tle)
            res.raise_for_status()
            return res
        except:
            count += 1
            if notify is True and count <= 4:
                print("Timeout. Retry %d in 3 times..." % count)
    if num is None:
        raise TimeoutError("Can't connect to "+url+".Please check your Internet configuration.")
    else:
        raise TimeoutError("Can't connect to "+url+str(num)+".Please check your Internet configuration.")

def getSoup(res):
    soup = bs4.BeautifulSoup(res.text, features="html.parser")
    return soup

def getImageNum(soup):
    b = soup.select("#middleContainer")              # find image num
    picNumString = b[0].text
    picNumPosStart = picNumString.find("xkcd.com")
    picNumPosEnd = picNumString.find("Image URL")
    picNum = picNumString[(picNumPosStart + 9):(picNumPosEnd - 2)]
    return picNum

def getImageUrl(soup):
    k = soup.select("#comic img")
    picUrl = k[0].get("src")  # //img.xxxxxx
    return picUrl

def writeFile(num, pic_res, pic_link, path="G:\\work\\gjmtest\\comicsplus2\\"):
    f = open(path + num + '_' + os.path.basename(pic_link), "wb")
    for chunk in pic_res.iter_content(100000):
        f.write(chunk)
    f.close()

def errorRetry():
    for i in errList:                               # for each picture number (error occurred)
        download(i)

def download(i):                                    # download particular picture
    print("Downloading picture %d..." % i)
    try:
        res = getResource(url, num=i, notify=True)
    except:
        mutex.acquire()
        errList.append(i)
        print("Error occurred: picture %d !!!" % i)
        mutex.release()
        return
    print("Parsing webpage of picture %d..." % i)
    soup = getSoup(res)
    num = getImageNum(soup)
    picurl = getImageUrl(soup)  # picture resources
    picres = requests.get("http:" + picurl)
    print("Writing picture %d..." % i)
    writeFile(num, picres, picurl)
    print("Succeeded in picture %d." % i)

def downloadSeq(start, end):                           # [start, end)
    for i in range(start, end):
        download(i)

def createThread(total_num):
    count = 1
    th = 0
    thread_list = []
    remain = total_num
    while remain > groupNum:
        thread_list.append(threading.Thread(target=downloadSeq, args=(count, count + groupNum)))
        thread_list[th].start()
        remain -= groupNum
        count += groupNum
        th += 1
    thread_list.append(threading.Thread(target=downloadSeq, args=(count, total_num)))
    thread_list[th].start()
    for t in thread_list:
        t.join()

def getTotalImage():  # one-time use
    try:
        res = getResource(url)
    except:
        print("Your network is too bad!")
        exit()
    soup = getSoup(res)
    num = int(getImageNum(soup))
    print("Total image number is %d." % num)
    print("Downloading process started.")
    return num

if __name__ == "__main__":
    startTime = time.time()
    createDir()
    totalNum = getTotalImage()
    threads = 5
    groupNum = math.ceil(totalNum / threads)

    createThread(totalNum)
    errorRetry()
    endTime = time.time()
    timeCost = round(endTime - startTime, 1)
    print("Done. Total time: %s sec." ,str(timeCost))

            
          

我保證,以后一定要 11 點準時睡覺 = =||

不說了,累死啦~趕快滾去睡


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 免费看一级欧美毛片视频 | 欧美一区二区三区黄色 | 九九精品影院 | 欧美黄色免费在线观看 | 国产精品久久做爰 | 九九影音 | 在线精品一区二区三区 | 久久久免费网站 | 国产综合社区 | 四虎国产精品永久地址49 | 色婷婷色 | 国产精品免费福利 | 特级毛片免费视频观看 | 成人久久18免费网 | 亚欧aⅴ天堂在线 | 日本在线无 | 免费高清成人啪啪网站 | 国产成人aa免费视频 | 91九色蝌蚪在线 | 久久精品免费在线观看 | 国产精品国偷自产在线 | 久久亚洲这里只有精品18 | 国产玖玖玖精品视频 | 亚洲国产成人久久综合区 | 国产成人精品久久二区二区 | a在线观看免费 | 欧美一级免费看 | 天天都色 | 国产亚洲一区二区麻豆 | 国产精品久久久99 | 国产精品99久久久久久人 | 国产精品99r8在线观看 | 国产专区日韩精品欧美色 | 久久在线中文字幕 | 免费国产不卡午夜福在线观看 | 国产理论最新国产精品视频 | 国产成人高清一区二区私人 | 亚洲成人在线免费 | 久久综合综合久久狠狠狠97色 | 亚洲在线免费观看 | 色综合久久久久综合99 |