项目原因:

最近在学习利用Python编写爬虫代码爬取网页数据,但学习内容主要是针对于窗口不变或者网页地址不变的网页信息提取。于是我在日常学习的基础上,做了一个针对于新增窗口页面数据提取的项目。

目录

1. 操作流程

1.1 常规找寻思路

 1.2 抓取思路

2. 代码实现

2.1 进入网站,抓取英雄名称

方法一:requests库

编辑 

方法二:request.urllib库

 2.2 定位搜索框,输入英雄名称,点击搜索按钮,搜索后点击头像。

 2.3 读取本地文件,抓取皮肤信息,保存到xls/xlsx/csv类型文件


1. 操作流程

1.1 常规找寻思路

平常我们想要查看一个英雄的皮肤的话,那常规的操作是,先打开王者荣耀的英雄资料页面

下拉页面发现有一个全部英雄的列表,同时列表有搜索框可以搜索英雄。

python 王者荣耀 资料 python爬取王者荣耀_爬虫

点击搜索英雄孙悟空, 英雄列表出现孙悟空的小图,这时需要点击孙悟空的头像跳转到孙悟空的英雄页面。页面包含英雄的技能介绍、英雄故事等信息,鼠标在皮肤小图移动时页面背景也会随之改变,若我们想要查看其它英雄的皮肤,需要返回搜索页面去搜索英雄名称。这就是常规查看一个英雄皮肤的流程,本项目的目的就是利用浏览器驱动抓取皮肤名称,以及皮肤小图和皮肤大图的链接。

python 王者荣耀 资料 python爬取王者荣耀_搜索_02

python 王者荣耀 资料 python爬取王者荣耀_爬虫_03

 1.2 抓取思路

大致思路:

先抓取所有英雄的名称,然后利用循环依次将英雄名称输入到搜索框,点击搜索按钮搜索到英雄,点击英雄头像跳转到英雄详情页面,抓取英雄页面的网页信息并写入到本地文件,之后再提取皮肤信息。然后关闭当前页面,返回搜索页面,输入下一个英雄的名称,重复上述操作。

分步实现:

  • 进入网站,抓取英雄名称,所需要的库:requests/selenium+bs/re
  • 定位搜索框,输入英雄名称,点击搜索按钮,搜索后点击头像,需要库:selenium
  • 读取新页面的网页数据并写入本地文件,需要库:os
  • 读取本地文件,抓取皮肤信息,保存到xls/xlsx/csv类型文件,需要库:os+bs/re+openpyxl+

2. 代码实现

2.1 进入网站,抓取英雄名称

Python里面有很多库可以进入网页爬取信息,其中request.urllib和requests是较为常用的库,可以随便选择其中的一个库进行爬取。requests是一个与urllib类似的http客户端,但使用比urllib更加简洁,并且针对具有反爬措施的网站,在爬取不到内容时requests不会像urllib一样报错。下面我将用两个库分别爬取网页,最后得到的结果都是一样的,大家想用哪一个都可以。

方法一:requests库

import requests
from bs4 import BeautifulSoup as bs
import re
def get_url():
    url='http://pvp.qq.com/web201605/herolist.shtml'
    response=requests.get(url)
    response.encoding=response.apparent_encoding
    #print(response.text)
    #多用apparent_encoding的结果进行中文页面内容的解析
    #也可以先返回bytes,再手动解码
    #response.content.decode('utf-8')/decode('gbk')与response.text都返回字符串
    soup_url=bs(response.text,'html.parser')
    soup_ul=soup_url.find('ul',class_="herolist clearfix")
    #print(soup_ul)
    soup_a=soup_ul.find_all('a')
    #print(soup_a)
    hero_name=re.findall(re.compile(r'<a.*?><img.*?>(.*?)</a>',re.S),str(soup_a))
    #print(hero_name)
    return hero_name
get_url()

方法二:request.urllib库

import urllib.request
from bs4 import BeautifulSoup as bs
import re
def get2_url():
    url='http://pvp.qq.com/web201605/herolist.shtml'
    response=urllib.request.urlopen(url)
    #print(response.read().decode('gbk'))
    responsetext=response.read().decode('gbk')
    #---------------------------------------------------------------------------
    #方法一:用正则表达式直接提取
    #find=re.compile(r'<li><a.*?><img.*?width="91".*?height="91" alt="(.*?)">.*?</a></li>',re.S)
    #hero_name=re.findall(find,responsetext)
    #列表返回的最后一个为"' + _cname + '",返回值时要删除
    #change_name=hero_name[:-1]
    #---------------------------------------------------------------------------
    #方法二:先转化成soup对象,再进行提取
    soup_url=bs(responsetext,'html.parser')
    soup_ul=soup_url.find('ul',class_="herolist clearfix")
    #print(soup_ul)
    soup_a=soup_ul.find_all('a')
    #print(soup_a)
    hero_name=re.findall(re.compile(r'<a.*?><img.*?>(.*?)</a>',re.S),str(soup_a))
    #print(hero_name)
    #----------------------------------------------------------------------------
    #return change_name
    return hero_name
get2_url()

python 王者荣耀 资料 python爬取王者荣耀_爬虫_04

 2.2 定位搜索框,输入英雄名称,点击搜索按钮,搜索后点击头像。

 因为在下面的过程中需要在搜索框中循环输入英雄名称,所以我们需要控制循环的次数,让次数小于英雄的个数,下面代码返回一共有93个英雄。

hero_name=get_url()
print(len(hero_name))

python 王者荣耀 资料 python爬取王者荣耀_python 王者荣耀 资料_05

由于英雄太多,为了方便实验,我们只选取上面返回的前十五个英雄进行信息抓取。 

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time

def select_name(hero_num):
    #hero_num为我们自定义的需要抓取的英雄个数
    url2='http://pvp.qq.com/web201605/herolist.shtml'
    browser=webdriver.Edge()
    #定义一个驱动器browser
    browser.set_window_size(1100,700)
    browser.get(url2)
    time.sleep(3)
    #让页面停留3秒,防止翻页太快抓取不到信息
    for i in range(hero_num): 
        #a.定位到输入框,循环在输入框输入英雄名字
        #<input type="text" id="search" name="search" class="herosearch-input" value="请输入你想要搜索的英雄名">
        input_box=browser.find_element(by=By.CLASS_NAME,value='herosearch-input')
        input_box.send_keys(hero_name[i])
        time.sleep(3)
        #b.定位到搜索框并点击搜索按钮
        #<a href="javascript:void(0);" class="herosearch-icon" title="点击搜索" id="searchBtn"></a>
        search_button=browser.find_element(by=By.CLASS_NAME,value='herosearch-icon')
        search_button.click()
        time.sleep(3)
        #点击英雄链接跳转页面
        #<ul class="herolist clearfix"><li><a href="herodetail/108.shtml" target="_blank"><img src="//game.gtimg.cn/images/yxzj/img201606/heroimg/108/108.jpg" width="91px" alt="墨子">墨子</a></li></ul>
        hero_url=browser.find_element(by=By.CLASS_NAME,value='herolist').find_element(by=By.TAG_NAME,value='a')
        hero_url.click()
        time.sleep(3)
        ws = browser.window_handles
        browser.switch_to.window(ws[1])
        #将页面定位到跳转的新页面,方便后面进行信息抓取和页面定位
        #c.抓取页面内容并写入本地文件
        os.makedirs('hero_skin',exist_ok=True)
        #创建一个名为'hero_skin'的文件夹
        filename='hero_skin/'+hero_name[i]+'.html'
        #在'hero_skin'的文件夹中为每个英雄创建后缀为.html的文件
        with open(filename,'w',encoding='utf-8') as file:
            file.write(browser.page_source)
            #page_source直接获取当前网页的全部页面数据
        #返回上一级页面继续搜索下一个英雄
        time.sleep(5)
        browser.close()
        #关闭当前页面
        browser.switch_to.window(ws[0])
        #切换到搜索页面
        input_box.clear()
        #清除原来的搜索框内容
select_name(hero_num=15)

通过这一步我们已经将15名英雄的所有网页数据保存在本地文件中了。

python 王者荣耀 资料 python爬取王者荣耀_爬虫_06

 2.3 读取本地文件,抓取皮肤信息,保存到xls/xlsx/csv类型文件

到了最后一步,需要从读取的网页数据中提取出皮肤名称、皮肤小图和皮肤大图,下面先观察网页数据或者本地html文件的详情,定位到需要抓取的内容。以云中君为例,如下所示:

python 王者荣耀 资料 python爬取王者荣耀_html_07

 所有的图片都在ul标签下的img标签里面,所以可以先定位ul标签,接着定位img标签。代码如下:

import openpyxl
def get_skin():
    for roots,dirs,files in os.walk('hero_skin'):
        pass
    for file in files:
        skin_list=[]
        with open(roots+'/'+file,'r',encoding='utf-8') as fl:
            print(f'正在提取{file}信息,稍等一下...')
            hero_page=fl.read()
            #print(hero_page)
            soup_hero=bs(hero_page,'html.parser')
            #print(soup_hero)
            #<ul class="pic-pf-list pic-pf-list3" ...>...</ul>
            try:
                soup_ul=soup_hero.find('ul',class_='pic-pf-list pic-pf-list3')
            except Exception as e:
                print(e)
                soup_ul=''
            #print(soup_ul)
            soup_img=soup_ul.find_all('img')
            #print(soup_img)
            for img in soup_img:
                skin_name=img['data-title']
                skin_small_url=img['src']
                skin_big_url=img['data-imgname']
                #print(skin_name,skin_small_url,skin_big_url)
                skin_list.append((skin_name,'http:'+skin_small_url,'http:'+skin_big_url))
            #print(skin_list)
            os.makedirs('王者英雄皮肤信息',exist_ok=True)
            herofile=openpyxl.Workbook()
            hero_sheet=herofile.create_sheet('皮肤详情',0)
            title = ['皮肤名称', '皮肤小图', '皮肤大图']
            hero_sheet.cell(1,1).value=title[0]
            hero_sheet.cell(1,2).value=title[1]
            hero_sheet.cell(1,3).value=title[2]
            for i_row in range(len(skin_list)):
                for i_col in range(len(title)):
                    hero_sheet.cell(i_row+2,i_col+1).value=skin_list[i_row][i_col]
            herofile.save('王者英雄皮肤信息/'+file[:-5]+'皮肤信息.xlsx')
#             with open(herofile,'w',encoding='utf-8',newline = '') as skin:
#                 skin_writer = csv.writer(skin)
#                 # 写表头,单行信息,用writerow方法
#                 title = ['皮肤名称', '皮肤小图', '皮肤大图']
#                 skin_writer.writerow(title)
#                 # 写数据,多行信息,用writerows方法,数据要放在嵌套的容器中
#                 skin_writer.writerows(skin_list)
get_skin()

到这我们已经将所需要的爬取的数据保存到本地文件中了,为了检验一下操作是否有效,随机点开一个英雄的文件查看。

python 王者荣耀 资料 python爬取王者荣耀_爬虫_08

 

python 王者荣耀 资料 python爬取王者荣耀_搜索_09

OK,大功告成,链接已经保存到本地文件了。最后,除了以上在搜索框输入英雄名字进行抓取的方法,还可以在全部英雄列表将英雄链接爬取下来,然后通过循环点击链接,之后跳转到新页面,爬取新页面内容,关闭新页面

python 王者荣耀 资料 python爬取王者荣耀_python_10