被遺忘的8張圖片(day2爬蟲的王姝慧的問題)

問題描述:
在day2的《青春有你2》選手信息爬取任務中。標答給出的圖片個數是482張,而且大部分的同學也爬去的是482張。
但是一位同學(在此手動@MR.GAO同學)由於代碼的優秀(在此不得不提,try-catch是個好東西),竟然爬出了490張。並在羣中提出了疑問。
原來問題出現在王姝慧的圖冊的問題上面。通過下面圖冊的編號可以發現,她有長達38張圖片(不得不感嘆一下,這圖片也太多了吧,一切問題的根源就在這裏)。
表達對於王姝慧這位選手的圖片指爬去了30張,但是人家明明有38張呀,那麼被遺忘的8張圖片去了哪裏呢。
題主就這個問題,進行了一番強勢debug!!!

在這裏插入圖片描述

問題根源

在這裏插入圖片描述
通過對源代碼的查看,不難看出,該代碼在渲染超過30張圖片(序號從0開始)的時候,對於30張以後的圖片的href是不會顯示出來的,進一步嘗試發現,從選中標號28即第29張圖片的時候,標號30即第31張圖片顯示了出現。這裏很明顯是一個ajax的異步加載。從標號28開始,會加載出後面的兩張圖片。
在這裏插入圖片描述

代碼分析

這裏不得不說一句:真的一切的存在都是有原因的。其實題主之前自己的代碼也是能夠發現這個文題的,但是題主沒有去深究他,遇到問題直接使用判空處理,然後爲空就略過。

題主代碼第一版

#題主代碼第一版
        for i in img_node_list:#img_node_list 爲所有的a節點的列表
                url = prifix+i['href']
                img_url_list.append(url)

第一版在第二行報錯,說有的i對象沒有href的屬性。當時還想報錯時候的i給輸出看了下,發現只有一個<a class=“pic-item” data-index=“30”></a>但是當時也沒有多想,就以爲是本來頁面上就是爲空的,也沒有去網頁上查看到底是爲什麼爲空。所有就有了第二版的偷懶做法。

題主代碼第二版

#題主代碼第一版
        for i in img_node_list:#img_node_list 爲所有的a節點的列表
            if 'href' in str(i):# 
                url = prifix+i['href']
                img_url_list.append(url)

這一版就是直接判斷i是否有href的屬性,有的話就繼續,沒有的話就跳過,就因爲這個偷懶,所有導致沒有發現問題所在。

##MR.GAO同學的代碼

   for pic in pic_list:
        try:
            pic_url = 'https://baike.baidu.com' + pic.attrs['href']
        except:
            print('a對象沒有href')
        response = requests.get(pic_url, headers=headers)
        soup = BeautifulSoup(response.text, 'lxml')
        src_target = soup.find('img', {'id': 'imgPicture'}).attrs['src']
        pic_urls.append(src_target)

可以發現,該同學這裏使用了一個try-except的方法進行了異常的捕獲。第一眼看他的代碼發現其實並沒有找到後面的url呀,應該也是隻能爬去30行圖片,後面的8張圖片是爬去不到的吧。但是該同學說自己是爬到了38張圖片的。然後這就讓我很迷了。都沒有找到後面的url,是怎麼把後面的圖片爬到的呢?

帶着這個問題,是這debug了一下他的代碼,發現王姝慧選手文件夾下面真的有38張圖片。(當時心裏是瞬間感覺這段代碼充滿着惡意,感覺對他失去了控制)
帶着不拋棄不放棄的心理,仔細看了一下圖片,發現從30張開始 後面的9張都長一個樣

破案了!!!

原來,該同學由於代碼的原因,即使後面的8個a元素沒有href對象,但是被except捕獲了沒有報錯,而且上一輪的pic_url也連續被使用了,所有從30-39的url都是同一個url,所有也就有了9個相同的圖片,後面8個沒有url的圖片都被最後同一個有url的圖片給替代了(備胎)

不過這個代碼肯定是達不到將8個遺忘的圖片找回來的功能的。所有題主在此進行了一番修改,力求把消失的8張圖片找回來。

I got you

對代碼做了改進,中心思想是在每一次打開圖片的時候,都將頁面中的pic-list節點下面的a元素統計進來,然後將其中href不爲空並且沒有在pic_list中出現過的a元素加進去

    a_list_tmp = []
    count1 = 0
    for pic in pic_list:
        if 'href' in str(pic):
            a_list_tmp.append(pic)
    pic_list = a_list_tmp
    a_list_tmp = []
    for pic in pic_list:
        count2 = 0
        count1 = count1 + 1
        print(count1)
        pic_url = 'https://baike.baidu.com' + pic.attrs['href']
        response = requests.get(pic_url, headers=headers)
        soup = BeautifulSoup(response.text, 'lxml')
        a_list_tmp = soup.find('div', {'class': 'pic-list'}).find_all('a')
        if count1 == 29:
            print(soup)
        for a in a_list_tmp:
            count2 = count2 + 1
            print('******{}'.format(count2))
            if 'href' in str(a) and a not in pic_list:
                pic_list.append(a)
    
		……
  #	這樣的話會講每次選中的那個a元素再次添加進去,因爲a元素被選中了就會添加一個selected的class
  #所有最後得到了pic_urls後 還需要對其去重
  pic_urls = set(pic_urls)

迷之尷尬的事情發生了

然而,事情並沒有想像中的那麼順利,迷之前端在頁面的時候如果當前點擊的是28的圖片,30的圖片鏈接會出來,但是當查看源碼的時候,其實鏈接並沒有出來,很密很密。
圖片爲證:
選中29號圖片後頁面上的審查代碼:
在這裏插入圖片描述
選中29號圖片後源代碼:
在這裏插入圖片描述
可以看到,在源代碼中,30後面的圖片的鏈接並沒有出來。好迷好迷!!!
頂不住了,睡覺了!!!
未完待續!!!
(我來填坑了)



可以確定後面的8張圖片是通過ajax動態加載的,那麼想到這個問題,第一個思路當然是打開強大的chrome瀏覽器的控制檯查看network裏面的請求了呀。所有有了下面的發現。
在這裏插入圖片描述
在這裏插入圖片描述

可以發現,當訪問的圖片從第22張開始的是多了一個getPhotos的請求。那麼下一步就是分析這個請求拿到了什麼。於是題主講返回的json數據解析後進行了查看:
首先是張這樣的,可以看到裏面有8個src(這個數字好巧呀,看到這裏心裏好激動。)
在這裏插入圖片描述
打開每一個src後可以發現:
在這裏插入圖片描述
然後直接複製裏面的鏈接打開,哇小姐姐出來了耶!(此處就不放小姐姐圖片了。)

My Solution

如果圖片數量超過30就模擬瀏覽器發送get請求得到動態加載的圖片數據

#如果圖片數量超過30就模擬瀏覽器發送get請求得到動態加載的圖片數據
def crawl_json_data():
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
    }
    url = 'https://baike.baidu.com/ajax/getPhotos?lemmaid=2306701&id=3177575&sublemmaid=24715125&aid=1&pn=30&rn=30'
    getpic_response = requests.get(url, headers=headers).text
    json_data = json.loads(str(getpic_response).replace("\'", "\""))
    print(json_data)
    with open('pic_res.json', 'w', encoding='UTF-8') as f:
        json.dump(json_data, f, ensure_ascii=False)

然後在原本的代碼中做如下修改,從json文件i裏面找到高清圖片的url添加到pic_urls裏面就行了

    if len(pic_list)>30:
        #如果圖片的個數大於30  則模擬瀏覽器發送請求 然後解析json拿到剩下的圖片的鏈接
        crawl_json_data()
        #解析json
        with open('pic_res.json', 'r', encoding='UTF-8') as file:
            json_array = json.loads(file.read())
            lists_list = json_array['data']['list']
            for li in lists_list:
                #會發現list節點下面的第三個元素是最大圖片的鏈接
                #通過下標訪問json 自己寫
                count = 0
                for key in li['sizes']:
                    count+=1
                    if count == 3:
                        key_2 = key

                img_bg_url = li['sizes'][key_2]['url']
                print(img_bg_url)
                pic_urls.append(img_bg_url)

至此 這個由8張消失的圖片引出的一個坑終於被自己使用一種偷懶的方法解決了!!!

最終效果圖(490張 不帶重複的圖片)

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章