学习pyplot子库的时候突然突发奇想,如果把我最常听的10首歌下下来,做一个扇形图,岂不是很美好?

    于是我就开始准备爬取了网易云

    很显然,网易云是Ajax异步加载(源网页上没有想要内容,需要先进母网页,再发数据包才行),因此需要分步进行爬取。然而,我查看了Network里的XHR,找到了它对应的方法——post方法;也找到了对应的请求参数:就一个,rc啥的,然而我在python中爬取却完全找不到内容,太气啦

     request也可以成功,返回值也是200,但是查看r.text却是个空字符串。于是我只能使用selenium的方法来爬了——因为查到了说selenium可以爬取ajax异步加载的网页,并且把动态的网页源代码变成静态源代码(我觉得其实就是保留每一步网页的源代码,而不是像普通方法那样看不到网页内容——我试过了,确实看到的和selenium爬下来的不一样)。我觉得selenium像是映下来的,给每个页面当前的源码拍个快照——你在检查里看到的是啥就是啥,完全搞下来。所以我学习了一下selenium爬取,尝试半天,爬下了前十首歌,结果如下:(我把歌名模糊了,但是你可以根据你的喜好下载你的网易云,然后显示完整歌名哦)

java selenium 异步页面_java selenium 异步页面

    源代码如下:

# -*- coding: utf-8 -*-"""Created on Mon Nov  2 22:23:03 2020@author: Sheng Lu"""import selenium,timefrom selenium import webdriverbrows=webdriver.Chrome()brows.get('https://music.163.com/#/user/home?id=358721785')time.sleep(7)loginbtn=brows.find_element_by_xpath("//a[@hidefocus='true' and @data-action='login']")brows.maximize_window()loginbtn.click()chbtn=brows.find_element_by_class_name('other')chbtn.click()moblogbtn=brows.find_element_by_xpath("//a[@data-action='login' and @class='u-btn2 u-btn2-2']")#moblogbtn.click()#这里没法login因为没有同意协议#这里有一个问题是,moblogbtn如果只用dataaction找的话,一定会“无法交互”,因为上面的那个登录#按钮的dataaction也是这个protocol=brows.find_element_by_xpath("//input[@id='j-official-terms']")protocol.click()moblogbtn.click()phnumber=brows.find_element_by_xpath("//input[@placeholder='请输入手机号']")#手机号登录,因此需要在这里填写你的手机号和密码phnumber.send_keys('在这里填写你的手机号')password=brows.find_element_by_xpath("//input[@placeholder='请输入密码']")password.send_keys('这里填写你的密码')'''‘loginbtn2=brows.find_element_by_xpath("//a[@class='j-primary']")loginbtn2=brows.find_element_by_xpath("//a[@class='j-primary']")loginbtn2=brows.find_element_by_xpath("//a[@class='u-btn2-2']")这我真不知道咋回事,感觉是没写全class···奇怪,有时候要全有时候又不要全'''loginbtn2=brows.find_element_by_xpath("//a[@data-action='login' and @class='j-primary u-btn2 u-btn2-2']")loginbtn2.click()time.sleep(2)brows.switch_to_frame('contentFrame')chspan=brows.find_element_by_xpath("//span[@data-action='songsall' and @id='songsall']")chspan.click()brows.find_element_by_xpath("//a[@href='/user/songs/rank?id=358721785']")'''morebtn=brows.find_element_by_xpath("//a[@href='/user/songs/rank?id=358721785']")morebtn.click()morebtn.click()morebtn=brows.find_element_by_xpath("//a[@href='/user/songs/rank?id=358721785']")morebtn.click()morebtn=brows.find_element_by_xpath("//a[@href='/user/songs/rank?id=358721785']")morebtn.click()'''#这一块我本来想把排名前100的都给爬下来,无奈,居然点不动那个查看更多按键,说不可交互,奇怪。#接下来开始BeautifulSoup解析查找对应的tag标签。bs的一个好处就是把一个个标签作为单位,这样搜的#时候只需要搜标签,而不需要像纯字符串一样一个一个搜文字!time.sleep(2)from bs4 import BeautifulSoupbs=BeautifulSoup(brows.page_source)print(brows.page_source)#bs.find_all('li')#bs.find_all('div',class='ttc')#bs.find_all(class='ttc')#bs.find_all('div')#bs.find_all()#bs.find_all('class'="unit")#bs.find_all(class=="unit") #失败的试验,说明,class在用的时候一定要写class_!或者干脆什么都不写。bs.find_all('span',"unit")#像这样,默认class'''bs.find_all('span',"span")bs.find_all('li')bs.find_all('ttc')bs.find_all('div','ttc')bs.find_all('div',class='ttc')'''#在根据输出看怎么样定位到那些元素,这是selenium的懒方法——边做边看bs.find_all('div',class_='ttc')namelst=bs.find_all('div',class_='ttc')for tag in namelst:    print(tag.b.string)import ostimelst=bs.find_all('span',class_='times')#for tag in timelst:#    print(tag.name)for tag in timelst:    print(tag.string)a=[]for tag in timelst:    a.append(tag.string)dic=dict()b=[]for tag in namelst:    b.append(tag.b.string)c=[]for i in a:    i=i[:-1]    i=int(i)    c.append(i)del afor i in range(10):    dic[b[i]]=c[i]import matplotlib.pyplot as pltlabels=[]for key in dic:    labels.append(key)x=[]for key in dic:    x.append(dic[key])plt.rcParams['font.family']='SimHei'    colors=['red','#4169E1','purple','green','yellow','orange','grey','pink','#9932CC','grey']plt.pie(x,labels=labels,counterclock=False,startangle=180,radius=1.5,wedgeprops={'linewidth':1,'edgecolor':'black'},autopct='%.1f%%',textprops={'fontsize':15},colors=colors)#plt.savefig('MyPie.png')#这里飘了,想爬取前100名听歌歌单了time.sleep(2)js="var q=document.documentElement.scrollTop=200"  brows.execute_script(js) time.sleep(2)morebtn=brows.find_element_by_xpath('//div[@]/a[@href="/user/songs/rank?id=358721785"]')morebtn.click()ch=brows.find_element_by_id('songsall')ch.click()time.sleep(2)bs2=BeautifulSoup(brows.page_source)import reregex=re.compile('\d+')taglist=bs2.find_all('li',id=regex)print(taglist)namelst2=[]for tag in taglist:    namelst2.append(tag.b.string)numberlst2=[]for tag in taglist:    numberlst2.append(tag.find('span',class_='times f-ff2').string)count=0for string in numberlst2:    string=string[:-1]    string=int(string)    numberlst2[count]=string    count=count+1plt.pie(numberlst2,labels=namelst2,counterclock=False,startangle=180,radius=1.5,wedgeprops={'linewidth':1,'edgecolor':'black'},autopct='%.1f%%',textprops={'fontsize':15},colors=colors)plt.savefig('MyPie2.png')

    这个代码你们也可以直接用哦,只要有python,弄到IDLE里,只需要在29行和31行两处填写你的用户名和密码就好了(记住一定要是手机号,不能是什么邮箱之类的,因为这个模拟登陆路径是用的手机号登录路径)

    Purely a process-oriented programming呀!

我学到的最核心的东西:

    ①selenium生成的webdriver对象(记作brows),查看对应页源代码的语句是:

    brows.page_source

    即(页_源),这里的source是一个名词,记。

    然后就可以接上BeautifulSoup了

    bs的一个好处就在于,把一个个标签变成了对象(查找的时候以对象为单位进行查找),就可以以标签为单位来搜索内容了,你搜了标签名找到了对应的标签,就可以使用标签对象的各种用法来直接找到下面的子标签了!

    比如如果这个tag下面只有一个div,甭管在下面哪一级,直接tag.div就可以;如果tag下面有好几个div,分属不同的类,可以参考下面部分的代码(试着画了一个条形图)

    ——bar图和直方图的区别在实践中一目了然,bar图就是不同东西出现频率多少的,而直方图是不同区间频率多少的。刻画对象不一样,一个是不同物品,一个是不同连续区间,数值型!nb!

    tag也可以用find方法!也可以用find_all方法,本质上说对bs对象进行find其实就是全页面根tag的find,find返回字符串,find_all返回列表。

    进阶用法:find和find_all方法如何查找not only指定名字的标签,but also更细化为具有某个属性的这个名字的标签?

     tag.find_all('标签名',id='').

    ③元素定位通法

       i.能用id只用id,一个id在一个页面只能出现一次,而class可以出现多次(多个元素可以属于同一个类)

      ii.Xpath掌握啦!

      “//标签名[@对应属性名1=’‘ and @对应属性名2=’‘······]”,注意使用and!

      而如果这个在页面没法唯一指定,可以使用上一级标签,如我的例子中对于more标签的定位。//more[]/.注意,“标签名[]”,这是定位一个标签的方法,无论在那一级都可以用!//的意思应该就是,无论这个标签在哪一级,只要符合标准的,咱都要它。而如果只用/的话,那么是在根标签下面找那个名字的标签,找不到就完了。

    ④元素定不到位的原因:

    1.元素在子框架里(iframe里switch_to_frame('id或class'))

    2.元素还没加载出来:

    这个

    特别关键!

    特别关键!

    特别关键!

    selenium不论爬取还是模拟操作的时候,当存在页面跳转(如click)之后,一定要等几秒(设置sleep时间),因为程序一句一句运行0.0几秒,网页加载再快也达不到,因此一定要等几秒。

    3.元素不唯一:

    例如我在定位网易云手机号登录的标签的时候提示notiteractable,我想起来原来一开始的登录按钮也是这个class的,这样定位也有问题,因此需要更为具体而详细的指定。

   ④新学习:当需要页面下滑时的通用语句

js="var q=document.documentElement.scrollTop=200"  #这是从上往下拉的语句,也有从下往上拉,暂时不学啦brows.execute_script(js)

   让浏览器执行js语句!这句话只需要修改后面的数值就可以控制下拉页面的量。因为有的元素——比如网易云页面上的“查看更多”,当没有下拉到哪里时是不显示的······那个数据包不传递。总之就是无法定位到元素

   诶?或者说,

   是不是当浏览器当前你眼睛能看到的页面里没有那个元素,就无法定位到元素?

 (因为同样的问题也出现在了一开始定位登录标签里面,如果我不最大化窗口,或者手动最大化,那么是定位不到登录标签的······)

   emm,有趣!

   ⑤emm,所以又有学习:selenium爬虫的核心,就是不断寻找新的元素,点击,然后进入目标页面,或许目标页面源代码,然后beautifulsoup是用来提取!

    主要是提取方便!因为变成一个个标签之后就可以指定对应标签当中的string属性!而标签只需要标签名1.标签名2这样来定位就可以了,也很方便!

    试想,如果源代码是纯纯的string,怎么定位呢?是吧?

    所以selenium的核心在于操作浏览器找到目标页面,然后返回对应页面源代码;bs的核心用意在于把源代码中标签对象化之后提供一个清晰的数据提取路径!两者是有明显的先后顺序,和不同的分工用意!

    np!

    有学习

    这个爬虫项目真的让我学到了好多新东西,真高兴~

   所以以后爬取各种网站都有了一个新途径——selenium爬取!

   其实selenium一点都不复杂,不需要直接在brows对象中定位元素输出内容,只需要brows.page_source就可以,剩下的事交给美丽汤来处理

java selenium 异步页面_标签名_02

   棒棒棒,太棒了,哈哈哈哈哈哈哈!cyzj,llunb!