摘要:對于這次的爬蟲來說,由于網易云音樂以及音樂網頁中大部分元素都是使用渲染生成的,因此選擇使用來完成這次的腳本。可以發現網易云音樂的手機版歌單地址是。現在已經支持網易云音樂與音樂歌單的互相同步。
本文主要介紹selenium在爬蟲腳本的實際應用。適合剛接觸python,沒使用過selenium的童鞋。(如果你是老司機路過的話,幫忙點個star吧)
項目地址https://github.com/Denon/sync...
selenium介紹selenium官網. 直接引用官網的話
Selenium automates browsers. That"s it! What you do with that power is entirely up to you. Primarily, it is for automating web applications for testing purposes, but is certainly not limited to just that. Boring web-based administration tasks can (and should!) also be automated as well.
簡單翻譯下
selenium是一個自動化的瀏覽器, 主要使用來做web應用的自動化測試。
個人認為用selenium主要的好處是: 可以解析js渲染的頁面。對于這次的爬蟲來說, 由于網易云音樂以及qq音樂網頁中大部分元素都是使用js渲染生成的, 因此選擇使用selenium來完成這次的腳本。
環境準備python 2.7
selenium
phantomjs / Chromium
selenium 運行需要額外的瀏覽器支持. 其中phantomjs可以在這里下載, Chromium可以在這里下載。 前期debug階段建議使用 Chromium 。
詳細的包依賴請查看github項目
初始化selenium
從網易云音樂歌單網頁中獲取歌曲列表
登錄qq音樂
搜索音樂
添加到qq音樂的歌單中
初始化seleniumfrom selenium import webdriver # 這里是使用PhantomJs, 如果使用chromium則使用webdriver.Chrome(), # 并替換對應的驅動路徑即可 phantomjs_driver = phantomjs_driver_path opts = Options() opts.add_argument("user-agent={}".format(headers["User-Agent"])) browser = webdriver.PhantomJS(phantomjs_driver)從網易云音樂中獲取音樂
對于一般爬蟲來說, 如果能用手機端網頁爬取那就無腦選網頁端爬取。可以發現網易云音樂的手機版歌單地址是: http://music.163.com/m/playli... 。 這個地址么一看就知道, 后面那串id就是歌單id。chrome瀏覽器打開調試工具, 可以看到所有的歌曲都在...里面。 那么直接用requests + beautifulsoup 爬取元素就好。 這里就不深入討論了。 具體的代碼請參考項目
登錄qq音樂一般來說,爬蟲做登錄有兩種選擇。一種是抓包,分析登錄請求體,直接模擬登錄,這種穩定性較好,只要解析出請求體后,登錄一般都能成功。一種是模擬正常登錄操作,在輸入框中輸入賬號密碼,然后點擊登錄按鈕來登錄,這種穩定性較差,有可能會有各種意外的情況,比如驗證碼之類的。這里當然要使用第二種來做(不然就跑題了)。
首先打開qq音樂網站, 發現qq登錄的按鈕在
這里介紹selenium第一個函數find_element_by_xpath,這個函數就是根據element的xpath來獲取元素的。
browser.find_element_by_xpath("/html/body/div[1]/div/div[2]/span/a[2]").click()
點擊完后, 頁面應該會彈出一個登錄框, 不過默認應該是掃碼登錄, 這個時候就要點擊下“帳號密碼登錄”來切換。可以發現, 這個切換按鈕的id是switcher_plogin. 那么使用selenium的 find_element_by_id 函數:
browser.find_element_by_id("switcher_plogin").click()
按理來說這段代碼應該能運行成功,但是如無意外的話,我們只能獲得一個報錯
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"id","selector":"switcher_plogin"}
這是什么情況???
細心點觀察可以發現,這個彈出來的登錄框是在一個iframe里面。這個時候需要使用到另外一個函數switch_to.frame,
# 切換iframe browser.switch_to.frame("frame_tips") browser.find_element_by_id("switcher_plogin").click() # 輸入賬號密碼, 用到send_keys函數 user_input = browser.find_element_by_id("u") user_input.send_keys("qq_account") pwd_input = self.browser.find_element_by_id("p") pwd_input.send_keys("qq_password") # 最后要切換回來 browser.switch_to.default_content()
可以發現ok了,然后賬號密碼等輸入框直接用上面介紹過的函數直接獲取就行。
搜索歌曲在瀏覽器中打開qq音樂實際搜索一下,發現搜索的url是 https://y.qq.com/portal/search.html#page=1&searchid=1&remoteplace=txt.yqq.top&t=song&w=%E6%B5%AE%E5%A4%B8,可以看到搜索的關鍵詞在 w 這個參數里面,并且中文字是被url encode過的。那么這里使用python內置的urllib2包即可
from urllib2 import quote url_sw = quote(search_word.encode("utf8"))
添加到歌單由于python2坑爹的編碼問題, 一般把字符存儲成unicode, 在需要使用的時候再轉換對應編碼比較合適。
人工添加歌單的操作實際分為三步:
鼠標移動到歌曲上
點擊 + 號
點擊對應的歌單
觀察html元素可以發現,搜索出來的歌曲都在
all_song = browser.find_elements_by_class_name("songlist__list")
點擊完以后,可以看到歌單的html元素都在里面。
all_playlist = browser.find_elements_by_class_name("operate_menu__item")
而其中每個歌單是以data-dirid這個屬性來區分的,這里介紹另外一個元素選擇函數find_element_by_css_selector
browser.find_element_by_css_selector("a[data-dirid="{}"]").click()
那么就這樣結束了么?
當然不是! 實際運行中發現,這里面大部分元素都是js渲染生成的,直接使用selenium函數去獲取這些元素,很大可能會報錯
selenium.common.exceptions.ElementNotVisibleException: Message: element not visible
碰到這種情況,最好的解決辦法是,用selenium直接執行js腳本來調用元素,selenium執行js腳本的函數為execute_script
browser.execute_script("document.getElementsByClassName("songlist__list")[0].firstElementChild.getElementsByClassName("list_menu__add")[0].click()"
而js代碼是可以直接在瀏覽器上debug的,一般現在瀏覽器上執行成功在復制回來。
其他一些輔助方法在實際操作中,雖然使用的方法是正確的,但會出現很多意外的情況導致本次操作是失敗的,這時候就需要來一次重試來解決問題(如果一次重試解決不了問題,那就來兩次)。這里使用一個裝飾器來寫
def retry(retry_times=0, exc_class=Exception, notice_message=None, print_exc=False): """retry_times: 重試次數 exc_class: 捕捉的異常 notice_message: 提示信息 print_exc: 是否打印錯誤信息 """ def wrapper(f): @functools.wraps(f) def inner_wrapper(*args, **kwargs): current = 0 while True: try: return f(*args, **kwargs) except exc_class as e: if print_exc: traceback.print_exc() if current >= retry_times: raise RetryException() if notice_message: print notice_message current += 1 return inner_wrapper return wrapper總結
介紹了selenium獲取元素的各種用法,更多的請參考文檔
解決使用selenium可能會碰到的一些坑。
最后在安利一次github項目, https://github.com/Denon/sync...。歡迎點贊以及提issue。現在已經支持網易云音樂與qq音樂歌單的互相同步。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/38639.html
摘要:基于等開發一款移動端音樂,界面參考了安卓版的網易云音樂布局適配常見移動端。圖標使用阿里巴巴圖標庫,中間的唱片旋轉動畫使用了實現。搜索功能實現功能搜索歌手歌單歌曲熱門搜索數據節流上拉刷新保存搜索記錄。 基于 Vue(2.5) + vuex + vue-router + vue-axios +better-scroll + Scss + ES6 等開發一款移動端音樂 WebApp,UI ...
摘要:,在聽音樂的時候忽然想聽騰格爾的鋼鐵之翼隱形的翅膀,在網易云上卻找不到,就很氣。于是想到了做一個,音樂搜索的功能,把所有想聽的歌,能夠一次性在酷狗網易云蝦米等平臺上找找完。本項目非常適合新手練習熟悉全家桶,歡迎哦。 React-music React Music WebApp,在聽音樂的時候忽然想聽騰格爾的鋼鐵之翼(隱形的翅膀),在網易云上卻找不到,就很氣。于是想到了做一個,音樂搜索的...
摘要:通常這種加密都是通過加密的,所以首先要找到這個有加密算法的。追蹤函數,發現它指向一個叫的函數,仔細研究許久后大概知道加密算法經兩次加密獲得,模式為,偏移量為。 前言 某寶評論區已經成功爬取了,jd的也是差不多的方法,說實話也沒什么好玩的,我是看上它們分析簡單,又沒加密才拿來試手的。如果真的要看些有趣的評論的話,我會選擇網易云音樂,里面匯聚了哲學家,小說家,story-teller,皮皮...
摘要:引言馬上情人節就要來了,是否需要一首歌來撫慰你,受傷或躁動的心靈。來吧,今天教你用行代碼搞定熱門歌單。爬取的效果如下總結本文旨在安撫你因情人節受傷的小心靈,同時帶你入個爬蟲的門,感受下的強大。 0. 引言 馬上314情人節就要來了,是否需要一首歌來撫慰你,受傷或躁動的心靈。來吧,今天教你用15行代碼搞定熱門歌單。學起來并聽起來吧。 本文使用的是Selenium模塊,它是一個自動化測試工...
閱讀 1718·2021-10-18 13:34
閱讀 3906·2021-09-08 10:42
閱讀 1551·2021-09-02 09:56
閱讀 1605·2019-08-30 15:54
閱讀 3126·2019-08-29 18:44
閱讀 3297·2019-08-26 18:37
閱讀 2212·2019-08-26 12:13
閱讀 453·2019-08-26 10:20