1. 程式人生 > >利用selenium抓取英雄聯盟桌布

利用selenium抓取英雄聯盟桌布

本部落格主要來利用selenium這一利器來爬取LOL官網各個英雄面板的桌布,注意是桌布,不是圖片!桌布是圖片,但圖片不是桌布。

selenium是一個自動化測試工具,利用它可以驅動瀏覽器執行一些特定的操作,比如點選、下拉等操作,由於selenium是模擬人的行為,所以對一些JavaScript渲染的網頁特別有效 ,而且不易被封號或者反爬限制,但是爬取效率慢。selenium安裝以及基本方法的使用詳見https://blog.csdn.net/LuoZheng4698729/article/details/78032362?locationNum=5&fps=1博主暱稱羅政,如果有機會,我會把我自己當時做的關於selenium庫的筆記發上來,與大家一起交流。

下面我們進入正題,怎麼利用selenium爬取LOL官網的所有英雄面板桌布,網上有很多的關於爬取王者榮耀的英雄面板桌布,LOL英雄桌布的爬取相對王者榮耀的難度大,首先LOL官網上面的英雄資訊全是非同步載入的(非ajax載入),也就是說用一般的方法難以找到各個英雄資訊的連結,而王者榮耀的官網的面板資訊在原始碼中就可以找到,所以難度不大,直接利用requests和正則即可。

首先,我們進入英雄聯盟官網的資料庫URL=http://lol.qq.com/web201310/info-heros.shtml(一波回憶殺。。。),然後檢視原始碼,我們在原始碼裡面看不到相關的英雄資料,同樣的我們利用審查元素,也是找不到一些關於英雄ajax載入的資訊。

於是,我們想到利用selenium來抓取資訊,首先進入該頁面,然後通過點英雄影象,利用審查元素檢視得到如下圖所示的元素,我們可以看到在a 節點下面有個連結,點選進去,得各個單獨的英雄的資訊,這樣我們到時候就可以在單獨的頁面提取英雄的面板資訊

             

到此,我們已經完成了程式的一小步,部分程式如下:

from selenium import webdriver
import time ,requests
hero=[]
brower = webdriver.Chrome()   #初始化,利用谷歌驅動
brower.get('http://lol.qq.com/web201310/info-heros.shtml')  #模擬瀏覽器登入url初始網站
time.sleep(3)   #設定等待,可以設定高階等待方式----顯示等待
brower.execute_script("window.scrollBy(0,1500)")   #滑動滑鼠滾輪,使其到達頁面尾部。
infor=brower.find_element_by_css_selector('#jSearchHeroDiv') #定位元素
#print(infor.text)
links=infor.find_elements_by_css_selector('li>a')
for link in links :
    urls=link.get_attribute('href')  
    hero.append(urls.split())    
print(hero) #定位多元素,利用for一個個的將各個英雄的詳細資訊連結放入一個列表中

繼續,我們在各個英雄單獨頁面中,點選背景圖片,點選審查元素,如圖所示,我們可以看到,該元素中只有一個面板的大桌布,而該英雄其他面板資訊沒有出現。這樣我們該怎麼辦?

其實也很簡單,我們點選其他面板的任意一個,再點選審查元素,我們就可以看到該英雄所有面板的資訊,如下圖所示,當然,selenium中的點選可以用.cick()來實現, 最後我們就是根據elements裡面的節點來定位元素,最後提取元素屬性。

該節的程式碼如下:

for m in range(len(hero)) :          ##單獨的提取一個個英雄的詳細資訊網址
    #print(hero[m][0])
    brower.get(hero[m][0])          #進入單個英雄的網頁
    time.sleep(2)
    brower.execute_script("window.scrollBy(100,800)")    #將網頁移動到視野可見,兩個值#(100,800)可以自己設定。
    brower.find_element_by_css_selector('#skinNAV').find_elements_by_css_selector('li a')[1].click()            #模擬點選
    skins=brower.find_element_by_css_selector('#skinBG').find_elements_by_css_selector('li')         #定位面板資訊位置
    for skin in skins :
        skin_name=skin.get_attribute('title')
        img_url=skin.find_element_by_css_selector('img').get_attribute('src')
        if skin_name=='預設面板':
            skin_name='預設面板'+hero[m][0].split('?')[1]    #資料處理,因為每一個英雄都有##一個預設面板,所以將英雄的預設面板名稱改為預設面板+英雄id,這樣在下載的時候,前面英雄的預設面板####不會被後面英雄的預設面板沖掉。
        img=requests.get(img_url)    ####requests請求img所在的網址
        print(skin_name,img_url)
        filename='C:\\Users\\FangWei\\Desktop\\網路爬蟲\\爬取英雄聯盟桌布\\'+skin_name+'.jpg'
        with open(filename,'wb') as f:
            f.write(img.content)     ####下載圖片
            print('圖片已下載')

 最後,提出一個問題:我們在定位元素時候是在#skinBG的節點下得到的面板圖片,多一步點選,有人說,我在#skinNAV節點下就可以得到該英雄的所有面板資訊,而且也有圖片,為什麼我還要利用你這個方式,還多一步點選?原因如下:

利用#skinBG下面的節點時候獲得的面板是980*500畫素,而利用上面問題提出的方法得到的是60*60畫素,我們爬取的是桌布,不是圖片,所以我們不能利用#skinNAV節點下的元素來獲取img網址,再下載。

爬取到的部分結果截圖如下:

本內容的所有程式碼:

# -*- coding: utf-8 -*-
"""
Created on Mon May  7 22:47:56 2018

@author: NJUer
"""
from selenium import webdriver
import time ,requests
hero=[]
brower = webdriver.Chrome()
brower.get('http://lol.qq.com/web201310/info-heros.shtml')
time.sleep(3)
brower.execute_script("window.scrollBy(0,1500)")
infor=brower.find_element_by_css_selector('#jSearchHeroDiv')
#print(infor.text)
links=infor.find_elements_by_css_selector('li>a')
for link in links :
    urls=link.get_attribute('href')
    hero.append(urls.split())
print(hero)
for m in range(len(hero)) :
    print(hero[m][0])
    brower.get(hero[m][0])
    time.sleep(2)
    brower.execute_script("window.scrollBy(100,800)")
    brower.find_element_by_css_selector('#skinNAV').find_elements_by_css_selector('li a')[1].click()
    skins=brower.find_element_by_css_selector('#skinBG').find_elements_by_css_selector('li')
    for skin in skins :
        skin_name=skin.get_attribute('title')
        img_url=skin.find_element_by_css_selector('img').get_attribute('src')
        if skin_name=='預設面板':
            skin_name='預設面板'+hero[m][0].split('?')[1]
        img=requests.get(img_url)
        print(skin_name,img_url)
        filename='C:\\Users\\FangWei\\Desktop\\網路爬蟲\\爬取英雄聯盟桌布\\'+skin_name+'.jpg'
        with open(filename,'wb') as f:
            f.write(img.content)
            print('圖片已下載')
    
            
            

               原創不易,如若轉載,請註明出處,謝謝!!!