selenium(自動化測試工具可用於在爬蟲中解決js動態加載問題)
簡介(本質就是模仿瀏覽器工作)
Selenium 是什么?一句話,自動化測試工具。它支持各種瀏覽器,包括 Chrome,Safari,Firefox 等主流界面式瀏覽器,如果你在這些瀏覽器里面安裝一個 Selenium 的插件,那么便可以方便地實現Web界面的測試。換句話說叫 Selenium 支持這些瀏覽器驅動。話說回來,PhantomJS(無頭瀏覽器)不也是一個瀏覽器嗎,那么 Selenium 支持不?答案是肯定的,這樣二者便可以實現無縫對接了。
然后又有什么好消息呢?Selenium支持多種語言開發,比如 Java,C,Ruby等等,有 Python 嗎?那是必須的!
安裝一下 Python 的 Selenium 庫,再安裝好 PhantomJS,不就可以實現 Python+Selenium+PhantomJS 的無縫對接了嘛!PhantomJS 用來渲染解析JS,Selenium 用來驅動以及與 Python 的對接,Python 進行后期的處理,完美的三劍客!
有人問,為什么不直接用瀏覽器而用一個沒界面的 PhantomJS(無頭瀏覽器) 呢?答案是:效率高!而爬蟲中使用它主要是為了解決requests無法直接執行JavaScript代碼的問題 selenium本質是通過驅動瀏覽器,完全模擬瀏覽器的操作,比如跳轉、輸入、點擊、下拉等,來拿到網頁渲染之后的結果,可支持多種瀏覽器。
前面爬取站長素材的時候圖片是必須有瀏覽器視窗才加載。用selenium可以解決這種視窗加載問題。
環境安裝
1、下載安裝selenium
pip3 install selenium
2、下載瀏覽器對應版本的驅動(這里最好用谷歌瀏覽器方便強大)
http://chromedriver.storage.googleapis.com/index.html
selenium演示:
from selenium import webdriver import time #指定瀏覽器,參數是瀏覽器驅動的路徑,前面加上r防止轉義 driver = webdriver.Chrome(r"./chromedriver.exe")#打開瀏覽器 #用get打開頁面 driver.get("https://www.baidu.com") # 下面是演示一下其他操作 # #查找頁面的“設置”選項,並點擊 # driver.find_elements_by_link_text('設置')[0].click() # time.sleep(1) # #打開搜索設置選項 # driver.find_elements_by_link_text('搜索設置')[0].click() # time.sleep(1) # # 選中每頁顯示50條 下拉不能先點擊 直接先選中找到子元素點擊 # m = driver.find_element_by_id("nr") # time.sleep(2) # m.find_element_by_xpath('//*[@id="nr"]/option[3]').click() # time.sleep(0.7) # #類名可能多個 會返回列表 因此取第一個 id,xpath都是唯一的 # driver.find_elements_by_class_name("prefpanelgo")[0].click() # time.sleep(1) # #處理彈出的警告頁面 確認accept() 取消dismiss() # driver.switch_to_alert().accept() #找到搜索框 輸入關鍵字(.send_keys) driver.find_element_by_id('kw').send_keys("校花") time.sleep(0.5) #找到搜索按鈕 提交 driver.find_element_by_id("su").click() time.sleep(2) #找到圖片搜索欄鏈接 看圖片 driver.find_elements_by_link_text("圖片")[0].click() time.sleep(3) #退出瀏覽器 關閉瀏覽器 driver.quit()
selenium爬取雪球 投資的網站首頁(涉及到js動態加載)
from selenium import webdriver from lxml import etree import time driver = webdriver.Chrome("./chromedriver.exe") #讓瀏覽器指定url發起請求 經測試它有動態加載數據 driver.get("https://xueqiu.com/") time.sleep(3) #獲取瀏覽器打開的當前頁面的源碼數據******* page_text = driver.page_source #用etree解析數據 tree = etree.HTML(page_text) text = tree.xpath('//*[@id="app"]/div[3]/div[1]/div[2]/div[2]/div[1]/div[3]/p/text()')[0] print(text) time.sleep(2) driver.quit() ###打印結果: """好買商學院專注出品原創內容,內容包括金融理財知識,基金基礎知識,股票,債券,大家想了解更多, 就點擊頭像關注好買商學院吧,更多精彩內容等你來看喔! 股市簡介: 周五(9.27), 今日早盤兩市微幅高開后分化,滬指橫盤震盪,深成指、創業板指雙雙走高漲超1%。截止收盤,滬指漲0.11%,報收293..."""
selenium相關行為動作的制定:
from selenium import webdriver import time driver = webdriver.Chrome("./chromedriver.exe") #打開淘寶網站 driver.get("https://www.taobao.com") time.sleep(2) #定位到想要找的節點輸入框 input_text = driver.find_element_by_id("q") #輸入你想輸入的關鍵字send_keys() input_text.send_keys("華為") time.sleep(3) #類選擇器 找到節點按鈕 btn = driver.find_element_by_css_selector(".btn-search") #點擊按鈕發送 btn.click() time.sleep(2) #執行js程序(js注入) driver.execute_script("window.scrollTo(0,document.body.scrollHeight)") time.sleep(2) driver.quit()
運行有點久,時間可以自行調節。
動作鏈:
from selenium import webdriver import time #導入動作鏈模塊 from selenium.webdriver import ActionChains driver = webdriver.Chrome("./chromedriver.exe") #這個菜鳥教程里面有iframe標簽以內的html標簽 driver.get("https://www.runoob.com/try/try.php?filename=jqueryui-api-droppable") #如果定位節點在標簽iframe內,那么則必須使用switch_to進行iframe的切換 driver.switch_to.frame("iframeResult") #開始定位節點(選中節點) sm_div = driver.find_element_by_id("draggable") #實例化一個動作鏈對象(將瀏覽器對象作為參數傳入) action = ActionChains(driver) #點擊並且長按(節點對象) action.click_and_hold(sm_div) #開始模擬人拖動 for i in range(5): #讓sm+div移動 action.move_by_offset(17,0).perform()#一定要加perform(立即執行動作鏈)不然不會移動 容易忘記他***************** time.sleep(0.6) time.sleep(3) #退出瀏覽器 driver.quit()
無頭瀏覽器(PhantomJS停止更新了,因此用谷歌的無頭瀏覽器):
from selenium import webdriver from lxml import etree import time #無頭瀏覽器設置(*********增加爬取效率) from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu') #無頭瀏覽器需要傳入參數在實例化的瀏覽器對象中***** driver = webdriver.Chrome(executable_path="./chromedriver.exe",options=chrome_options) #讓瀏覽器指定url發起請求 經測試它有動態加載數據 driver.get("https://xueqiu.com/") time.sleep(3) #獲取瀏覽器打開的當前頁面的源碼數據******* page_text = driver.page_source #用etree解析數據 tree = etree.HTML(page_text) text = tree.xpath('//*[@id="app"]/div[3]/div[1]/div[2]/div[2]/div[1]/div[3]/p/text()')[0] print(text) time.sleep(2) driver.quit()
規避被監測(用於反反爬措施):
from selenium import webdriver from lxml import etree import time #*****************規避被監測*********************** from selenium.webdriver import ChromeOptions option = ChromeOptions() option.add_experimental_option('excludeSwitches', ['enable-automation']) #無頭瀏覽器設置(*********增加爬取效率) from selenium.webdriver.chrome.options import Options chrome_options = Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu') #無頭瀏覽器需要傳入參數在實例化的瀏覽器對象中 driver = webdriver.Chrome(executable_path="./chromedriver.exe",options=option,chrome_options=chrome_options) #讓瀏覽器指定url發起請求 經測試它有動態加載數據 driver.get("https://xueqiu.com/") time.sleep(3) #獲取瀏覽器打開的當前頁面的源碼數據******* page_text = driver.page_source #用etree解析數據 tree = etree.HTML(page_text) text = tree.xpath('//*[@id="app"]/div[3]/div[1]/div[2]/div[2]/div[1]/div[3]/p/text()')[0] print(text) time.sleep(2) driver.quit()
模擬qq空間登錄:
from selenium import webdriver from lxml import etree import time driver = webdriver.Chrome(executable_path='./chromedriver.exe') driver.get('https://qzone.qq.com/') # 在web 應用中經常會遇到frame 嵌套頁面的應用,使用WebDriver # 每次只能在一個頁面上識別元素,對於frame 嵌套內的頁面上的元素, # 直接定位是定位是定位不到的。這個時候就需要通過switch_to.frame()方法將當前定位的主體切換了frame 里。 driver.switch_to.frame('login_frame') driver.find_element_by_id('switcher_plogin').click() time.sleep(3) #如果有別人的qq號 先清除 driver.find_element_by_id('u').clear() # 這里填寫你的QQ號 driver.find_element_by_id('u').send_keys('1259553287') time.sleep(3) #如果有別人的密碼 driver.find_element_by_id('p').clear() time.sleep(4) driver.find_element_by_id('p').send_keys('xxxxxxxxx') # 這里填寫你的QQ密碼 time.sleep(3) driver.find_element_by_id('login_button').click() time.sleep(5) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) driver.execute_script('window.scrollTo(0,document.body.scrollHeight)') time.sleep(2) # page_text = driver.page_source # # tree = etree.HTML(page_text) # # 執行解析操作 # li_list = tree.xpath('//ul[@id="feed_friend_list"]/li') # for li in li_list: # text_list = li.xpath('.//div[@class="f-info"]//text()|.//div[@class="f-info qz_info_cut"]//text()') # text = ''.join(text_list) # print(text + '\n\n\n') driver.close()
執行JavaScript
對於某些操作,Selenium API並沒有提供。比如,下拉進度條,它可以直接模擬運行JavaScript,此時使用execute_script()
方法即可實現,代碼如下: