心得:每天进步一点点,不懂得去查询,去学习,自己慢慢会进步的更多。
自己在学习过程中总结出来的爬虫的过程:
1.导入库,确定要用到的库
2.确定要爬取的url:
动态网页往往隐藏了在XHR,JS页面内,需要发掘和寻找,找出的数据往往是json格式的数据,需要进一步去提取。(ajax加载)
今天的重点在这里,如何破解ajax网页,抓取想要的内容。
3.数据解析:
三种解析方式,正则表达式,BeautifulSoup,xpath 提取需要的数据
4.持久化存储:
动态加载实例
1.豆瓣电影名称和评分的抓取
看看豆瓣排行榜的网页:
可以看到预览(preview)这一栏的东西只是一个空壳子,而且此网页的请求的地址和我们网站输入的地址一样,所以更加确定这是一个ajax请求的网站了。
找不到我们需要的电影名称和评分,我们就需要去ALL里面找其他的返回网页,看看有没有我们需要的关键字。
在一个top_list的一栏中找到了我们需要的信息,但它是以json格式存储的,所以我们此页面对相应的url发出请求,才可以获得完整的数据,再进行解析,筛选。
此网页是一个get并且带参数的,所以我们也需要再代码中加入参数进行抓取,带参数的url问号之后的参数可以删掉,将参数的值加入params中传入请求。
介绍一种读取json格式的方法,有时对json格式内容不好抓取,可以将json转换为更清晰的格式:
将json转换为更清晰的格式
看代码:
#coding=utf-8
import requests
import json
dou_url="https://movie.douban.com/j/chart/top_list"
params={
"type": "25", #5动作 #11剧情 24喜剧 20恐怖 10悬疑 19惊悚
"interval_id": "100:90",
"action": "",
"start": "0", #从第几部电影去取
"limit": "1000" #一次取多少部电影
}
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"
}
response=requests.get(url=dou_url,params=params,headers=headers)
for i in response.json():
if float(i['score']) >= 9:
print(i['title']+" : "+str(i['score']))
结果:
PS C:\Users\TianJian\Desktop\python> & C:/Users/TianJian/AppData/Local/Microsoft/WindowsApps/python.exe c:/Users/TianJian/Desktop/python/requests_1028/豆瓣电影高分.py
大雄的怀念奶奶 : 9.5
拽妹黛薇儿要上大学了没 : 9.4
千与千寻 : 9.3
机器人总动员 : 9.3
大闹天宫 : 9.3
虚幻勇士 : 9.3
苏联动画大师作品精选集 : 9.3
2.网易云音乐爬取,附加音乐的歌词。
网易云的动态加载做到了极致,它的音乐播放地址是一个外部链接,歌词链接也是一个外部链接,先看看它对应的url是什么:
因为它是动态加载我直接找到了,它对应的动态加载的url。
可以看到歌词的参数是被加密过的,我们不可能对加密的参数再进行请求,所以直接找到了它的外部
链接地址:
url="http://music.163.com/song/media/outer/url?id=1400256289.mp3" #外链播放地址
lrc_url="http://music.163.com/api/song/lyric?id=3932159&lv=1&kv=1&tv=-1" #外链歌词地址
我们拿到了外部链接地址,只需要再拿到对应的id就可以抓到对应的歌和歌词。
#coding=utf-8
import os
import re
import json
import requests
from lxml import etree
from bs4 import BeautifulSoup
filepath="C:\\Users\\TianJian\\Desktop\\python\\数据解析1107\\top_music\\" #定义存储路径
if not os.path.exists(filepath): #创建路径
os.mkdir(filepath)
headers={ #定义headers
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"
}
def down_song(song_url,song_path,name,headers): #获得song_url后,下载歌曲
song_r=requests.get(url=song_url,headers=headers).content
with open(song_path,"wb") as f:
f.write(song_r)
print(name+" : 下载完成 ")
def down_lyric(lrc_url,lyric_path,name,headers): #获得lyric_url后,下载歌词
r=requests.get(url=lrc_url,headers=headers).text
try: #有些歌曲歌词不存在,需要用try过度
lyric=json.loads(r)['lrc']['lyric'] #歌词url是一个json格式的文件,我们需要加载才可以使用
lyric_r=re.sub(r'\[.*\]','',lyric) #正则取剔除无用的信息
with open(lyric_path,"w",encoding="utf-8") as f:
f.write(lyric_r)
print(name+" : 歌词 下载完成 ")
except:
print(name+"的歌词不存在~~~")
pass
#url="http://music.163.com/song/media/outer/url?id=1400256289.mp3" #外链播放地址
#lrc_url="http://music.163.com/api/song/lyric?id=3932159&lv=1&kv=1&tv=-1" #外链歌词地址
#url="https://music.163.com/discover/toplist?id=3779629" #top榜
#url="https://music.163.com/discover/toplist?id=1978921795" #电音榜
url="https://music.163.com/discover/toplist?id=2250011882" #抖音榜
song_base_url="http://music.163.com/song/media/outer/url?id="
lrc_base_url = 'http://music.163.com/api/song/lyric?id='
s = requests.session()
r=s.get(url=url,headers=headers).content #需要content来提取信息
etree=etree.HTML(r)
title=etree.xpath('//a[contains(@href,"song?")]/text()')[:-3] #抓取歌名,后三位无用信息,切片拿掉
id=etree.xpath('//ul[@class="f-hide"]/li/a/@href') #抓取歌id
for name,i in zip(title,id): #遍历
song_id=i.split('=')[-1] #分割,取得id
song_url=song_base_url+song_id+".mp3" #歌url加工
song_path=filepath+name+".mp3" #歌存储路径加工
lrc_url=lrc_base_url+song_id+'&lv=1&kv=1&tv=-1' #词url加工
lyric_path=filepath+name+".txt" #词存储路径加工
down_song(song_url,song_path,name,headers) #分别调用
down_lyric(lrc_url,lyric_path,name,headers)
3.千千音乐爬取:
看看动态的mp3信息:
url内含有一串加密过的字符串,我们不能对加密的字符串进行提取,继续找,在js页面中找到了关于音乐id关联的东西:
然后我们对此网页进行解析发现,替换id之后可以将对应的音乐直接访问,所以我们需要抓取id就行,我们用静态网页抓取的方法抓取了hot_top页面歌曲的id,逐一进行下载存储。
#coding=utf-8
import requests
from lxml import etree
import json
import os
filepath="C:\\Users\\TianJian\\Desktop\\python\\数据解析1107\\music\\"
# for tu_file in os.listdir(filepath): #删除文件夹内的文件
# os.remove(filepath+str(tu_file))
if not os.path.exists(filepath):
os.mkdir(filepath)
url="http://music.taihe.com/top/dayhot"
base_url="http://musicapi.taihe.com/v1/restserver/ting?method=baidu.ting.song.playAAC&songid="
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.70 Safari/537.36"
}
r=requests.get(url=url,headers=headers).content.decode()
f_etree=etree.HTML(r)
music_name=f_etree.xpath('//div[@class="song-item"]/span[@class="song-title "]/a[contains(@href,"/song/")]/text()')
music_id=f_etree.xpath('//li/div[@class="song-item"]/span[@class="song-title "]/a[contains(@href,"/song/")]/@href')
#print(len(music_id))
for id,name in zip(music_id,music_name):
second_url=base_url+id.split('/')[-1]
#print(second_url,name)
sec_r=requests.get(url=second_url,headers=headers).text
sec_etree=etree.HTML(sec_r)
three_url=sec_etree.xpath('//body//text()')[0]
three_u=json.loads(three_url)
three_ur=three_u['bitrate']['show_link']
three_r=requests.get(url=three_ur,headers=headers).content
if '/' in name:
name=name.replace('/','')
downloadpath=filepath+name+".mp3"
with open(downloadpath,'wb') as f:
f.write(three_r)
print(name+" 下载完成")
mp3存储时,写入的格式为wb格式