一 . 圖片懶加載技術
案例分析:抓取站長素材http://sc.chinaz.com/中的圖片數據
import requests from lxml import etree if __name__ == "__main__": url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html' headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) \
Chrome/69.0.3497.100 Safari/537.36', } #獲取頁面文本數據
response = requests.get(url=url,headers=headers) response.encoding = 'utf-8' page_text = response.text #解析頁面數據(獲取頁面中的圖片鏈接)
#創建etree對象
tree = etree.HTML(page_text) div_list = tree.xpath('//div[@id="container"]/div') #解析獲取圖片地址和圖片的名稱
for div in div_list: image_url = div.xpath('.//img/@src') image_name = div.xpath('.//img/@alt') print(image_url) #打印圖片鏈接 # print(image_name)#打印圖片名稱
運行結果發現,我們可以獲取到圖片名稱,但是獲取到的鏈接為空,這就是圖片懶加載的原因
圖片懶加載的概念:
圖片懶加載是一種網頁優化技術,當你請求網頁的時候,如果所有圖片一下全加載出來會影響網頁加載效率的,
為了解決這個問題,前后端協同工作,使圖片在瀏覽器當前窗口才加載出來,達到減少首屏圖片請求次數,這種就稱為圖片懶加載
網站一般實現圖片懶加載的技術
在網頁源碼中,在img標簽中首先會使用這個'偽屬性'(通常使用src2,original...)去存放真正的鏈接,
當圖片出現到可視化窗口的時候,會動態的替換成src屬性,完成圖片加載
通過細致觀察頁面的結構后發現,網頁中圖片的鏈接是存儲在了src2這個偽屬性中
import requests from lxml import etree if __name__ == "__main__": url = 'http://sc.chinaz.com/tupian/gudianmeinvtupian.html' headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) \
Chrome/69.0.3497.100 Safari/537.36', } #獲取頁面文本數據
response = requests.get(url=url,headers=headers) response.encoding = 'utf-8' page_text = response.text #解析頁面數據(獲取頁面中的圖片鏈接)
#創建etree對象
tree = etree.HTML(page_text) div_list = tree.xpath('//div[@id="container"]/div') #解析獲取圖片地址和圖片的名稱
for div in div_list: image_url = div.xpath('.//img/@src2') #src2偽屬性
image_name = div.xpath('.//img/@alt') print(image_url) #打印圖片鏈接
print(image_name)#打印圖片名稱
二 . selenium
為什么要使用selenium?
有些網站的數據是動態加載的,如果用requests是不能獲取到數據的,用selenium通過驅動瀏覽器,完全模擬瀏覽器操作,比如下拉,單擊,跳轉等,這樣就可以獲取到數據
環境安裝
下載安裝selenium:pip install selenium 下載瀏覽器驅動程序: http://chromedriver.storage.googleapis.com/index.html 查看驅動和瀏覽器版本的映射關系: http://blog.csdn.net/huilan_same/article/details/51896672
操作前需要知道的知識
# 元素定位
find_element_by_id() find_element_by_name() find_element_by_class_name() find_element_by_tag_name() find_element_by_link_text() find_element_by_partial_link_text() find_element_by_xpath() find_element_by_css_selector()
簡單使用與效果展示
from selenium import webdriver from time import sleep # 后面是你的瀏覽器驅動位置,記得前面加r'','r'是防止字符轉義的
driver = webdriver.Chrome(r'驅動程序路徑') # 用get打開百度頁面
driver.get("http://www.baidu.com") # 查找頁面的“設置”選項,並進行點擊
driver.find_elements_by_link_text('設置')[0].click() sleep(2) # 是為了看的更清楚 # 打開設置后找到“搜索設置”選項,設置為每頁顯示50條
driver.find_elements_by_link_text('搜索設置')[0].click() sleep(2) # 選中每頁顯示50條
m = driver.find_element_by_id('nr') sleep(2) m.find_element_by_xpath('//*[@id="nr"]/option[3]').click() m.find_element_by_xpath('.//option[3]').click() sleep(2) # 點擊保存設置
driver.find_elements_by_class_name("prefpanelgo")[0].click() sleep(2) # 處理彈出的警告頁面 確定accept() 和 取消dismiss()
driver.switch_to_alert().accept() sleep(2) # 找到百度的輸入框,並輸入 美女
driver.find_element_by_id('kw').send_keys('美女') sleep(2) # 點擊搜索按鈕
driver.find_element_by_id('su').click() sleep(2) # 在打開的頁面中找到“Selenium - 開源中國社區”,並打開這個頁面
driver.find_elements_by_link_text('美女_百度圖片')[0].click() sleep(3) # 關閉瀏覽器
driver.quit()
上述的class和id都是通過網頁源代碼找到的
-- 來一個有常用的功能簡易版使用
from selenium import webdriver from time import sleep # 使用谷歌瀏覽器,填寫瀏覽器驅動位置
driver = webdriver.Chrome(r'./chromedriver.exe') # 打開網址用get
bro = driver.get('http://www.baidu.com') sleep(2) # 找到搜索框的id
content_input = driver.find_element_by_id('kw') # 輸入內容
content_input.send_keys('庫里') sleep(2)
# 清空用clear() # content_input.clear()
# 找到搜索按鈕的id
btn = driver.find_element_by_id('su') btn.click() sleep(3) # 退出
driver.quit()
執行js代碼
from selenium import webdriver from time import sleep # 使用谷歌瀏覽器,填寫瀏覽器驅動位置
driver = webdriver.Chrome(r'./chromedriver.exe') driver.get('https://xueqiu.com') sleep(3) # 實現滾輪向下滑動,第一個參數是橫向滾輪,第二個參數是縱向
js = 'window.scrollTo(0,document.body.scrollHeight)'
# 執行js代碼
driver.execute_script(js) sleep(2) # 每執行一次就向下滑動一下
driver.execute_script(js) sleep(2) # 這樣就能獲取到動態加載的數據了
print(driver.page_source) # 退出
driver.quit()
谷歌無頭瀏覽器,是一款無界面的谷歌瀏覽器
# 谷歌無頭瀏覽器,不出現可視化界面
from selenium import webdriver from selenium.webdriver.chrome.options import Options from time import sleep # 創建一個參數對象,用來控制chrome以無界面模式打開
chrome_options = Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu') # 使用谷歌瀏覽器,填寫瀏覽器驅動位置
browser = webdriver.Chrome(executable_path=r'./chromedriver.exe', options=chrome_options) # 打開網址用get
bro = browser.get('http://www.baidu.com') sleep(2) # 找到搜索框的id
content_input = browser.find_element_by_id('kw') # 輸入內容
content_input.send_keys('庫里') sleep(2) # 找到搜索按鈕的id
btn = browser.find_element_by_id('su') btn.click() sleep(3) # 截屏,沒啥意義 # browser.save_screenshot('./curry.png')
# 退出
browser.quit()
向前和后退
import time from selenium import webdriver browser=webdriver.Chrome(r'./chromedriver.exe') browser.get('https://www.baidu.com') browser.get('https://www.taobao.com') browser.get('http://www.sina.com.cn/') browser.back() time.sleep(2) browser.forward() time.sleep(2) browser.close()
動作鏈(鼠標拖拽,鍵盤按鍵,這些動作的執行就是動作鏈)
from selenium import webdriver from selenium.webdriver import ActionChains import time browser = webdriver.Chrome() url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable' browser.get(url) # 當定位標簽存在iframe的時候需要用到switch_to
browser.switch_to.frame('iframeResult') # 里面是id # 初識位置
source = browser.find_element_by_id('#draggable') # 結束位置
target = browser.find_element_by_id('#droppable') # 創建一個動作鏈的對象
action = ActionChains(browser) action.drag_and_drop(source,target) # 執行動作鏈
aciton.perform() sleep(3) # 可以模擬人的拖動效果,慢慢的拖動 # 點擊長按 # actions.click_and_hold(source) # time.sleep(3) # for i in range(5): # # perform表示開始執行動作鏈 # action.move_by_offset(xoffset=17,yoffset=0).perform() # time.sleep(0.5)
browser.quit()
selenium規避檢測
現在不少大網站有對selenium采取了監測機制。比如正常情況下我們用瀏覽器訪問淘寶等網站的 window.navigator.webdriver的值為 undefined。
而使用selenium訪問則該值為true。
解決辦法
from selenium.webdriver import Chrome from selenium.webdriver import ChromeOptions option = ChromeOptions() option.add_experimental_option('excludeSwitches', ['enable-automation']) driver = Chrome(r'瀏覽器驅動程序路徑',options=option) # 其他操作不用變,再去console一下window.navigator.webdriver就顯示undefined了