您的位置:首页 > 其它

Selenium入门:爬取王者营地96英雄背景故事及技能信息

2020-01-12 12:47 423 查看

写在前面:

  1. 确实在需求面前去学习会比较有效果…硬记一条条语句不仅慢,,用的时候还要想“这为啥又不行…”
  2. 本来是想从知乎动手的…但是登陆都没做到emm…昨天还以为知乎很nb,selenium的反爬也太厉害了吧,然后做完这个之后才知道和人家没关系 只是因为自己啥也不会 是个憨憨…

代码

直接贴代码了,反正为了以后自己能看明白自己这毫无逻辑的代码,每一行都强行注释上了

from selenium import webdriver
import time
from selenium.webdriver.common.action_chains import ActionChains #用于实现鼠标悬停,改变特定div的display

#内容以字符串格式写入文档
def strWrite(url,text):
try:
f=open(url,'a',encoding='utf-8')
f.write(text+'\n')
f.close()
except Exception as ex:
print('写入出错')

#程序开头selenium打开浏览器,找到包含所需内容的一些操作
def mainProgram():
driver.maximize_window()#当前窗口最大化
driver.get('http://www.baidu.com')#进入百度

kw = driver.find_element_by_id('kw')#通过id找到百度输入框
kw.send_keys('王者营地')#搜索关键字通过send_keys('')
su = driver.find_element_by_id('su')#通过id找到百度搜索按钮
su.click()#点击搜索按钮
time.sleep(2)#等待2s

wzyd = driver.find_element_by_link_text('《王者荣耀助手》正式升级为《王者营地》-王者荣耀官方网站-腾讯...')#通过标签内容文字找到王者营地的官网
wzyd.click()#点击王者营地官网
time.sleep(5)#等待5s

driver.switch_to.window(driver.window_handles[1])  # 因为点击官网进入新的标签页,此语句进入所有页面里下标为1的页面
yxzl = driver.find_element_by_css_selector('.main-nav > li:nth-child(2) > a')#在表头找到“游戏资料”
yxzl.click()#点击“游戏资料”

time.sleep(3)#等待3s
driver.switch_to.window(driver.window_handles[2]) # 因为点击游戏资料进入新的标签页,此语句进入所有页面里下标为2的页面
js = "var q=document.documentElement.scrollTop=900"#js语句 将页面右方拖动条拖动至距离顶部900px的位置
driver.execute_script(js)#webdriver执行上一条js语句
allHeroSkills()#开始读取全部英雄的技能信息!(和他们的背景故事)

#一个英雄的特定技能的读取
def skills(num):
page=num-1#这里的page不要理解为页码,理解为“技能page”,如“技能1”,“技能2”。。存在原因是因为“技能0”听起来怪怪的,
#所以选择不用下标

ele = driver.find_elements_by_css_selector('html body div.wrapper div.zkcontent div.zk-con-box div.zk-con3.zk-con div.skill.ls.fl div.skill-info.l.info ul.skill-u1 li')
#找到技能栏那些技能的《li》标签的列表
ActionChains(driver).move_to_element(ele[page]).perform()#通过函数传进来的num,用这条语句实现鼠标停留在某一个指定技能上
oneskill_name=driver.find_elements_by_xpath('/html/body/div[3]/div[2]/div/div[1]/div[2]/div/div/div[{0}]/p[1]/b'.format(num))[0].text
#找到技能名称
oneskill_cd=driver.find_elements_by_xpath('/html/body/div[3]/div[2]/div/div[1]/div[2]/div/div/div[{0}]/p[1]/span'.format(num))[0].text
#找到技能冷却时间,CD
oneskill_blue=driver.find_elements_by_xpath('/html/body/div[3]/div[2]/div/div[1]/div[2]/div/div/div[{0}]/p[1]/span'.format(num))[1].text
#找到技能消耗的蓝量
oneskill_introduce=driver.find_elements_by_xpath('/html/body/div[3]/div[2]/div/div[1]/div[2]/div/div/div[{0}]/p[2]'.format(num))[0].text
#找到技能的具体介绍
oneskill_tips=driver.find_elements_by_xpath('/html/body/div[3]/div[2]/div/div[1]/div[2]/div/div/div[{0}]/div'.format(num))[0].text
#找到技能的小技巧(来自官方的小技巧可能会没什么卵用...)
strWrite(r'C:\Users\lcega\Desktop\1233.txt',oneskill_name+'   '+oneskill_cd+' '+oneskill_blue)#技能,cd,耗蓝放在一行输出,搭配strWrite函数写入指定地址的某个txt里
strWrite(r'C:\Users\lcega\Desktop\1233.txt',oneskill_introduce)#技能介绍写入txt (strwrite里添加了‘每写一次最后都加个换行符’,贼关键
strWrite(r'C:\Users\lcega\Desktop\1233.txt',oneskill_tips)#技能小提示写入txt

#通过函数名应该也能看懂我什么意思————————为了(for)代码量更少(less)而去(to)构造一个函数(circle),哈哈哈哈哈哈哈我真特娘是个人才
def forlesstoCircle(i):
time.sleep(1)#等待1s
for handle in driver.window_handles:
driver.switch_to.window(handle)#从现有网页开始一个个选中(最后必然是选中所有网页中打开时间最短的那个网页)
time.sleep(1)#等待1s

herostory = driver.find_element_by_xpath('/html/body/div[3]/div[1]/div/div/div[1]/div[2]/a[1]')#找到英雄故事那个按钮
herostory.click()#点击英雄背景故事按钮
storycontent = driver.find_elements_by_xpath('/html/body/div[4]/div[2]/p')#找到英雄背景故事内容存放位置。
#至于上几行 为啥要点那个按钮 因为要把包含背景故事的节点的祖宗节点的display改成block了才能xpath找到....可能不用,但是我今天刚学我只会这么解决。
for j in range(len(storycontent)):
strWrite(r'C:\Users\lcega\Desktop\1233.txt',storycontent[j].text)#背景故事的格式不统一也是个坑。。。有的是一个《p》里靠br换行,,有的是好几个《p》
#里面甚至还带着《b》

time.sleep(1)#等待1s
for handle in driver.window_handles:  # 始终获得当前最新的窗口
driver.switch_to.window(handle)
driver.find_element_by_xpath('/html/body/div[4]/div[1]/a').click()#单击弹出div的小叉叉,如果没有上一步重新选中当前窗口,就点不了,这也是个坑...

js = "var q=document.documentElement.scrollTop=400"#js语句,页面滑动到距离页面顶端400px的位置
driver.execute_script(js)#执行上一句js

skills(1) #读取技能1并存起来!!(就是被动那里...)
skills(2)#读取技能2并存起来!!   (实际上这才是1技能,比如孙尚香翻滚,干将护主邪冢那个击飞...)
skills(3)#读取技能3并存起来!!(实际上这才是2技能)
skills(4)#读取技能4并存起来!!(实际上这才是3技能)
fiveskillhero_list=[6,10,13,16,24,31,33,56]#(带被动总共5个技能的英雄要特殊处理....)
#盘古,李信,盾山,元歌,女娲,干将,大乔,兰陵王
if (i in fiveskillhero_list):#如果有5技能,就读取.....
skills(5)
time.sleep(1)#等待1s
driver.close()#关闭浏览器当前页面,,,如果想关所有页面用quit(),这个代码没用上
strWrite(r'C:\Users\lcega\Desktop\1233.txt', '\n\n\n')#每个英雄的背景故事和信息之间都间隔上3行,方便看
print('成功录入该英雄背景故事及技能详情,当前共计录入{0}位英雄'.format(i))#用于pycharm上方便看到哪一个英雄了,或者说白了,,到哪儿出问题了

#处理所有英雄的所有技能!!(以及他们的背景故事)
def allHeroSkills():
time.sleep(1)#等待1s
for i in range(1,61):#我的屏幕大小下移900后,最多能显示前60位英雄的头像(可供点击)
for handle in driver.window_handles:  # 一样,出现过很多回了 始终获得当前最后的窗口  每一次循环都来一次的原因是
driver.switch_to.window(handle)#driver.close()关闭一个窗口的时候,任何窗口都未被选中。。。
hero = driver.find_element_by_css_selector('.herolist > li:nth-child({0}) > a:nth-child(1) > img:nth-child(1)'.format(i))#通过循环来决定到哪个英雄了
hero.click()#点击这个英雄的头像
forlesstoCircle(i)#上面出现的强行封装函数
for handle in driver.window_handles: # 一样,出现过很多回了 始终获得当前最后的窗口  出现在这里的原因是方便下面的滑动,不选中页面 js也失效
driver.switch_to.window(handle)
js = "var q=document.documentElement.scrollTop=1500"    #js语句,页面滑动到距离页面顶端1500px的位置 刚刚移动了900,需要再移600(为啥600,我自己测的),所以900+600=1500
driver.execute_script(js)#执行上面的js语句
for i in range(61,97):#滑动右方的条以后,可以找到剩下那些英雄啦
for handle in driver.window_handles:  # 一样,出现过很多回了 始终获得当前最后的窗口  出现在这里的原因是...0.0(忘了,可能我是个憨憨)
driver.switch_to.window(handle)
hero = driver.find_element_by_css_selector('.herolist > li:nth-child({0}) > a:nth-child(1) > img:nth-child(1)'.format(i))#通过循环来决定到哪个英雄了
hero.click()#点击这个英雄的头像
forlesstoCircle(i)#又出现了!!!上面出现的强行封装函数!!

#主要函数main   这样我就可以说这个程序很简单,只需要两行.....
driver = webdriver.Firefox()  #给火狐的开车老司机起个名
mainProgram()  #开始主函数

成品

注意事项

过程中一些因为不懂selenium的规则 进度停滞的地方 记下来:

  1. 当打开新页面或有需要刷新的时候,一定要通过等待页面加载出来再点击…
    ①sleep(time)

    import time
    time.sleep(10)
    强制等待时间。不管浏览器是否加载完成,都必须强制等待10s时间

    ②implicity_wait(time)

    隐性等待是浏览器在time时间内加载完成则继续执行。
    隐性等待对整个driver都有作用,只需要设置一次
  2. 打开新页面的时候,对新页面操作前要先选中新页面(同理关闭)。

    driver.switch_to.window(driver.window_handles[1])#中括号内数字为页面下标0,1,2,3....

    或者

    for handle in driver.window_handles:
    driver.switch_to.window(handle)#从现有网页开始一个个选中
    (最后必然是选中所有网页中打开时间最短的那个网页)
  3. 滑动滚轮功能(没显示在屏幕里的元素不能点,通过这个功能让未显示的显示…如果其实能点当我没说…)
    让driver执行js语句达到效果

    js = "var q=document.documentElement.scrollTop=900"#js语句 将页面右方拖动条拖动至距离
    顶部900px的位置
    driver.execute_script(js)#webdriver执行上一条js语句
  4. selenium操作display=none的标签 css xpath什么的都找不到,必须先模拟用户操作改变对应的display才能进行下一步

    ①页面的点击弹出div,selenium操作的时候 弹出以后需要用第二条重新选中当前页面,不然关闭的小叉叉不好使。
    ②靠鼠标悬浮改变固定位置的div显示,可以通过将鼠标悬停在某位置

    from selenium.webdriver.common.action_chains import ActionChains
    ele = driver.find_elements_by_css_selector('  ')
    ActionChains(driver).move_to_element(ele[page]).perform()

写在后面

虽然可能很low,也有很多错误,而且我在结束之后还去搜了搜 “selenium爬虫的意义”…
但是好歹也算是入了门,之后被问起,也能说一句了解了

  • 点赞
  • 收藏
  • 分享
  • 文章举报
doudou_nc 发布了15 篇原创文章 · 获赞 15 · 访问量 1659 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: