其实我本来是想着只用BeautifulSoup去实现的,在获取到音乐的url我在想音乐的文件名很重要,不然下载下来觉得动听但是却要听歌识曲的话就毫无意义了。
我上网查了一下搜狗可以查某个公众号的文章,但是对爬虫有限制而且只能查看往期的十篇,在知乎上的回答发现了传送门这个网站。http://chuansong.me/如果对某个公众号的内容感兴趣又想在pc端查看的话,这是个很好的网站。
所以我下一个函数去获取网页当中音乐的名字,但是我这个时候发现一个我无法解决的问题。就是requests.get()获取网页源代码的过程中音乐播放器的内容还是在缓冲的,所以源代码部分是这样的:
<div class="aplayer" id="mvplayer0"><div style="padding: 10px; font-size: 10px; text-align: center;">声音资源加载中...</div></div>
但是在原网页中却是这样的
图片一
这个是缓冲好的结果,所以我打算独辟蹊径,改变方法,使用之前学习过的selenium的phantomJS,这个工具可以在不启动浏览器的情况下加载等待。
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
browser = webdriver.PhantomJS()
wait = WebDriverWait(browser,10)
def get_one_music_title(url):
browser.get(url)
title=None
try:
result = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mvplayer0 > div.aplayer-info > div.aplayer-music > span.aplayer-title')))
title = result.text
print(title)
except TimeoutException:
print("TimeoutException")
return title
这就是获取音乐的名字的函数,设置了一个等待,超时就TimeoutException异常。By.CSS_SELECTOR是通过SELECTOR确定元素的位置,可以通过Chrome浏览器右键检查,然后选中某一元素右键copy的copy selector复制到剪贴板。
图片二
这是音乐的url,我是在network里的media找到再返回源代码里查找的,而且这里不是HTML结构,所以用了正则表达。
def get_one_music_url(url):
soup = get_one_soup(url)
script = soup.find_all('script')
pattren = re.compile('url:\'(.*?)\',',re.S)
music = None
for item in script:
result = re.search(pattren,str(item))
if(result):
music = result.group(1)
print(result.group(1))
return music
最后实现单页面所有文章的抓取和翻页,贴上源码。
import re
import requests
import time
import urllib
from urllib import request
from bs4 import BeautifulSoup
import os
from selenium import webdriver
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
browser = webdriver.PhantomJS()
wait = WebDriverWait(browser,10)
def get_one_html(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'
}
html = requests.get(url, headers=headers).text
time.sleep(0.01)
return html
def get_one_soup(url):
html = get_one_html(url)
soup = BeautifulSoup(html, "lxml")
return soup
def get_one_music_url(url):
soup = get_one_soup(url)
script = soup.find_all('script')
pattren = re.compile('url:\'(.*?)\',',re.S)
music = None
for item in script:
result = re.search(pattren,str(item))
if(result):
music = result.group(1)
print(result.group(1))
return music
def get_one_page_url(url):
soup = get_one_soup(url)
articleUrl = []
pattern =re.compile('(/n/.*)',re.S)
for item in soup.find_all('a'):
result = re.search(pattern,item.get('href'))
if (result):
print("http://chuansong.me"+str(result.group(1)))
articleUrl.append("http://chuansong.me"+str(result.group(1)))
return articleUrl
def get_one_page_music(articleUrl):
for item in articleUrl:
music = get_one_music_url(item)
if music:
title = get_one_music_title(item)
download_music(music,title)
def download_music(music,title):
if title:
try:
if not os.path.isfile(title+".mp3"):
print(title+".mp3正在下载")
urllib.request.urlretrieve(music,title+".mp3")
except OSError:
print("OSError")
def get_one_music_title(url):
browser.get(url)
title=None
try:
result = wait.until(EC.presence_of_element_located((By.CSS_SELECTOR,'#mvplayer0 > div.aplayer-info > div.aplayer-music > span.aplayer-title')))
title = result.text
print(title)
except TimeoutException:
print("TimeoutException")
return title
def get_all_page():
url='http://chuansong.me/account/newWhatYouNeed?start='
urlList = []
for i in range(53):
urlList.append(url+str(i*12))
return urlList
def main():
urlList = get_all_page()
for url in urlList:
articleUrl = get_one_page_url(url)
get_one_page_music(articleUrl)
if __name__ == '__main__':
main()
最后看看结果:
图片三
图片四
好吧下次试一试下载自己喜欢的公众号文章。