使用slenium+chromedriver實現無敵爬蟲
@概述
- 通常各大網站的後臺都會有一定的反爬機制,既為了資料安全,也為了減小伺服器壓力
- 通常反爬的手段的方向,都是識別非瀏覽器客戶端,而selenium所做的事情,恰恰是驅動真正的瀏覽器去執行請求和操作,只不過訊號不是來源於滑鼠,而是來源於selenium的API(selenium本是一個自動化的測試工具)
- 自然人使用者能做的一切,selenium幾乎都驅動瀏覽器取做,無論是否有介面,包括輸入、點選、滑動,等等
- 然而到底是滑鼠操作的瀏覽器發起的請求還是API,對於服務端來說,是沒有任何差別的
- 所以說:做人難,做男人難,做一個後臺開發的男人難上加難,讓我們開始對其實施蹂躪吧
@一些掌故
- 早些的時候流行的組合並不是selenium+chrome瀏覽器驅動,而是selenium+phantomjs
- phantomjs是一款沒有介面的瀏覽器,業界稱作無頭瀏覽器(headless),由於沒有介面和渲染,其執行速度要大大優於有介面的瀏覽器,這恰恰是爬蟲喜歡的,因此紅極一時
後來chrome和火狐推出了無頭模式,且執行速度很流暢,phantomjs已然壽終正寢,因此我們表過不提
@開發環境的搭建(基於ubuntu)
安裝selenium:sudo pip install selenium
- 如果沒有則安裝chrome瀏覽器(儘量更新到58以上):http://www.linuxidc.com/Linux/2016-05/131096.htm
- 安裝chrome瀏覽器驅動(注意最新版本尾號是29而非9):https://www.cnblogs.com/Lin-Yi/p/7658001.html
@導包
# 匯入selenium的瀏覽器驅動介面
from selenium import webdriver
# 要想呼叫鍵盤按鍵操作需要引入keys包
from selenium.webdriver.common.keys import Keys
# 匯入chrome選項
from selenium.webdriver.chrome.options import Options
@第一個程式:抓取頁面內容,生成頁面快照
# 建立chrome瀏覽器驅動,無頭模式(超爽)
chrome_options = Options()
chrome_options.add_argument('--headless')
driver = webdriver.Chrome(chrome_options=chrome_options)
# 載入百度頁面
driver.get("http://www.baidu.com/")
# time.sleep(3)
# 獲取頁面名為wrapper的id標籤的文字內容
data = driver.find_element_by_id("wrapper").text
print(data)
# 列印頁面標題 "百度一下,你就知道"
print(driver.title)
# 生成當前頁面快照並儲存
driver.save_screenshot("baidu.png")
# 關閉瀏覽器
driver.quit()
@模擬使用者輸入和點選搜尋,跟真人操作一樣!
# get方法會一直等到頁面被完全載入,然後才會繼續程式,通常測試會在這裡選擇 time.sleep(2)
driver.get("http://www.baidu.com/")
# id="kw"是百度搜尋輸入框,輸入字串"程式猿"
driver.find_element_by_id("kw").send_keys(u"程式猿")
# id="su"是百度搜尋按鈕,click() 是模擬點選
driver.find_element_by_id("su").click()
time.sleep(3)
# 獲取新的頁面快照
driver.save_screenshot("程式猿.png")
# 列印網頁渲染後的原始碼
print(driver.page_source)
# 獲取當前頁面Cookie
print(driver.get_cookies())
# ctrl+a 全選輸入框內容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'a')
# ctrl+x 剪下輸入框內容
driver.find_element_by_id("kw").send_keys(Keys.CONTROL, 'x')
# 輸入框重新輸入內容
driver.find_element_by_id("kw").send_keys("美女")
# 模擬EnterEnter鍵
driver.find_element_by_id("su").send_keys(Keys.RETURN)
time.sleep(3)
# 清除輸入框內容
driver.find_element_by_id("kw").clear()
# 生成新的頁面快照
driver.save_screenshot("美女.png")
# 獲取當前url
print(driver.current_url)
# 關閉瀏覽器
driver.quit()
@模擬使用者登入
# 載入微博登入頁
driver.get("http://passport.weibo.cn/signin/login?entry=mweibo&r=http%3A%2F%2Fweibo.cn%2F&backTitle=%CE%A2%B2%A9&vt=")
time.sleep(3)
# 找到輸入框,鍵入使用者名稱和密碼
driver.find_element_by_id('loginName').send_keys("worio.hainan@163.com")
driver.find_element_by_id('loginPassword').send_keys("Qq94313805")
# 點選登入按鈕
driver.find_element_by_id('loginAction').click()
time.sleep(3)
# 快照顯示已經成功登入
print(driver.save_screenshot('jietu.png'))
driver.quit()
@使用cookies登入
# 載入知乎主頁,檢視快照知此時處於未登入狀態
driver.get("https://www.zhihu.com")
time.sleep(1)
print(driver.save_screenshot("zhihu_nocookies.png"))
# 操作瀏覽器登入知乎並抓包cookies
zhihu_cookies = {
# 'aliyungf_tc' : 'AQAAAAR4YFOeswAAnLFJcVRd4MKOTTXu',
'l_n_c': '1',
'q_c1': '8572377703ba49138d30d4b9beb30aed|1514626811000|1514626811000',
'r_cap_id': 'MTc5M2Y0ODUzMjc0NDMzNmFkNTAzZDBjZTQ4N2EyMTc=|1514626811|a97b2ab0453d6f77c6cdefe903fd649ee8531807',
'cap_id': 'YjQyZTEwOWM4ODlkNGE1MzkwZTk3NmI5ZGU0ZTY2YzM=|1514626811|d423a17b8d165c8d1b570d64bc98c185d5264b9a',
'l_cap_id': 'MGE0NjFjM2QxMzZiNGE1ZWFjNjhhZmVkZWQwYzBkZjY=|1514626811|a1eb9f2b9910285350ba979681ca804bd47f12ca',
'n_c': '1',
'd_c0': 'AKChpGzG6QyPThyDpmyPhXaV-B9_IYyFspc=|1514626811',
'_xsrf': 'ed7cbc18-03dd-47e9-9885-bbc1c634d10f',
'capsion_ticket': '2|1:0|10:1514626813|14:capsion_ticket|44:NWY5Y2M0ZGJiZjFlNDdmMzlkYWE0YmNjNjA4MTRhMzY=|6cf7562d6b36288e86afaea5339b31f1dab2921d869ee45fa06d155ea3504fe1',
'_zap': '3290e12b-64dc-4dae-a910-a32cc6e26590',
'z_c0': '2|1:0|10:1514626827|4:z_c0|92:Mi4xYm4wY0FRQUFBQUFBb0tHa2JNYnBEQ1lBQUFCZ0FsVk5DNjAwV3dCb2xMbEhxc1FTcEJPenpPLWlqSS1qNm5KVEFR|d89c27ab659ba979a977e612803c2c886ab802adadcf70bcb95dc1951bdfaea5',
'__utma': '51854390.2087017282.1514626889.1514626889.1514626889.1',
'__utmb': '51854390.0.10.1514626889',
'__utmc': '51854390',
'__utmz': '51854390.1514626889.1.1.utmcsr=zhihu.com|utmccn=(referral)|utmcmd=referral|utmcct=/',
'__utmv': "51854390.100--|2=registration_date=20150408=1'3=entry_date=20150408=1",
}
# 將使用者登入產生的cookies全部新增到當前會話
for k, v in zhihu_cookies.items():
driver.add_cookie({'domain': '.zhihu.com', 'name': k, 'value': v})
# 再次訪問知乎主頁並拍照,此時已經是登入狀態了
driver.get("https://www.zhihu.com")
time.sleep(3)
print(driver.save_screenshot("zhihu_cookies.png"))
# 退出瀏覽器
driver.quit()
@模擬滾動條的滾動(這個用常規的爬蟲很難實現)
# 載入知乎主頁
driver.get("https://www.zhihu.com")
time.sleep(1)
# 載入本地cookies實現登入
for k, v in zhihu_cookies.items():
driver.add_cookie({'domain': '.zhihu.com', 'name': k, 'value': v})
# 以登入狀態再次發起訪問
driver.get("https://www.zhihu.com")
time.sleep(3)
# 將頁面滾動到最後,執行多次
for i in range(3):
js = "var q=document.documentElement.scrollTop=10000"
driver.execute_script(js)
time.sleep(3)
# 截圖並退出,頁面側邊滾動條已經下滑了許多畫素
print(driver.save_screenshot("zhihu_scroll.png"))
driver.quit()
@一邊滾動一邊載入
- 唯品會首頁的女裝圖片,是一邊滾動一邊進行ajax非同步載入的
- 這個靠常規的抓包實現起來很麻煩
- 使用selenium我們只需模擬使用者多次下拉滾動條,一段時間之後再重新拿取渲染好的頁面原始碼,就可以像爬取靜態頁面那樣去爬取圖片了
- 類似這種操作,其實質就是開掛,是幾乎無法防守的
# 唯品會女裝圖片連結無法直接獲得
# 請求唯品會頁面
driver.get("https://category.vip.com/search-3-0-1.html?q=3|30036||&rp=30074|30063&ff=women|0|2|2&adidx=1&f=ad&adp=65001&adid=326630")
time.sleep(3)
# 逐漸滾動瀏覽器視窗,令ajax逐漸載入
for i in range(1, 10):
js = "var q=document.body.scrollTop=" + str(500 * i) # PhantomJS
js = "var q=document.documentElement.scrollTop=" + str(500 * i) # 谷歌 和 火狐
driver.execute_script(js)
print('=====================================')
time.sleep(3)
# 拿到頁面原始碼
html = etree.HTML(driver.page_source)
all_img_list = []
# 得到所有圖片
img_group_list = html.xpath("//img[contains(@id,'J_pic')]")
# img_group_list = html.xpath("//img[starts-with(@id,'J_pic')]")
# 正規表示式匹配
# img_group_list = html.xpath(r'//img[re:match(@id, "J_pic*")]',namespaces={"re": "http://exslt.org/regular-expressions"})
# 收集所有圖片連結到列表
for img_group in img_group_list:
img_of_group = img_group.xpath(".//@data-original | .//@data-img-back | .//@data-img-side")
print(img_of_group)
all_img_list.append('\n'.join(img_of_group) + '\n')
# 將收集到的資料寫入檔案
with open('vip.txt', 'w', encoding='utf-8') as f:
f.write('\n'.join(all_img_list))
# 退出瀏覽器
driver.quit()
相關文章
- 使用Go語言實現爬蟲功能Go爬蟲
- 微博爬蟲 java實現爬蟲Java
- 實用爬蟲-02-爬蟲真正使用代理 ip爬蟲
- 如何使用queue模組實現多執行緒爬蟲執行緒爬蟲
- 使用 HttpClient 和 HtmlParser 實現簡易爬蟲(轉載)HTTPclientHTML爬蟲
- scrapy-redis實現爬蟲分散式爬取分析與實現Redis爬蟲分散式
- Python實現微博爬蟲,爬取新浪微博Python爬蟲
- 爬蟲——爬取貴陽房價(Python實現)爬蟲Python
- ajax+php實現爬蟲功能PHP爬蟲
- 網路爬蟲——爬蟲實戰(一)爬蟲
- 使用Python爬蟲實現自動下載圖片Python爬蟲
- Python爬蟲的兩套解析方法和四種爬蟲實現Python爬蟲
- 使用java 爬蟲Java爬蟲
- python的爬蟲功能如何實現Python爬蟲
- nodejs + koa2 實現爬蟲NodeJS爬蟲
- Python爬蟲是如何實現的?Python爬蟲
- 運用node實現簡單爬蟲爬蟲
- 多執行緒爬蟲實現(上)執行緒爬蟲
- 爬蟲實戰爬蟲
- 爬蟲實戰(一):爬取微博使用者資訊爬蟲
- 大規模非同步新聞爬蟲: 用asyncio實現非同步爬蟲非同步爬蟲
- Python爬蟲教程-06-爬蟲實現百度翻譯(requests)Python爬蟲
- 使用爬蟲實現拼多多商家電話採集軟體爬蟲
- 【Python學習】爬蟲爬蟲爬蟲爬蟲~Python爬蟲
- Python爬蟲教程-05-python爬蟲實現百度翻譯Python爬蟲
- 爬蟲實現:根據IP地址反查域名爬蟲
- python實現selenium網路爬蟲Python爬蟲
- Disruptor 實踐:整合到現有的爬蟲框架爬蟲框架
- Python 爬蟲IP代理池的實現Python爬蟲
- Python Beautiful Soup+requests實現爬蟲Python爬蟲
- node.js實現爬蟲功能介紹Node.js爬蟲
- Java+MySQL實現網路爬蟲程式JavaMySql爬蟲
- urllib2實現簡單爬蟲爬蟲
- 怎麼使用爬蟲爬蟲
- node爬蟲-使用puppeteer爬蟲
- Python爬蟲之路-chrome在爬蟲中的使用Python爬蟲Chrome
- 爬蟲實戰scrapy爬蟲
- Python爬蟲-用Scrapy框架實現漫畫的爬取Python爬蟲框架