pyppeteer -- python版本的puppeteer,一個強大的chronium headless瀏覽器API
最近搞天貓用了一波兒,記錄一下。
先上文檔: https://miyakogi.github.io/pyppeteer/
舉個最簡單的例子入門一下:
比如打開百度,然后截圖

# coding:utf8 import asyncio from pyppeteer import launch async def main(): launch_kwargs = { # 默認無頭模式 # "headless": False, } # 啟動瀏覽器 browser = await launch(launch_kwargs) # 打開標簽頁 page = await browser.newPage() # 輸入網址並打開 await page.goto("http://www.baidu.com") # 獲取頁面元素 title = await page.title() print(title) # 關閉瀏覽器 await browser.close() return asyncio.get_event_loop().run_until_complete(main())
下面說一些小技巧:
1、啟動參數

launch_kwargs = { # 控制是否為無頭模式 "headless": False, # chrome啟動命令行參數 "args": [ # 瀏覽器代理 配合某些中間人代理使用 "--proxy-server=http://127.0.0.1:8008", # 最大化窗口 "--start-maximized", # 取消沙盒模式 沙盒模式下權限太小 "--no-sandbox", # 不顯示信息欄 比如 chrome正在受到自動測試軟件的控制 ... "--disable-infobars", # log等級設置 在某些不是那么完整的系統里 如果使用默認的日志等級 可能會出現一大堆的warning信息 "--log-level=3", # 設置UA "--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36", ], # 用戶數據保存目錄 這個最好也自己指定一個目錄 # 如果不指定的話,chrome會自動新建一個臨時目錄使用,在瀏覽器退出的時候會自動刪除臨時目錄 # 在刪除的時候可能會刪除失敗(不知道為什么會出現權限問題,我用的windows) 導致瀏覽器退出失敗 # 然后chrome進程就會一直沒有退出 CPU就會狂飆到99% "userDataDir": "", }
注意:同一個用戶目錄(userDataDir)不能被兩個chrome進程使用,如果你要多開,記得分別指定用戶目錄。否則會報編碼錯誤。
2、設置viewport
自動獲取當前屏幕大小並設置viewport

# coding:utf8 import asyncio from pyppeteer import launch def screen_size(): """使用tkinter獲取屏幕大小""" import tkinter tk = tkinter.Tk() width = tk.winfo_screenwidth() height = tk.winfo_screenheight() tk.quit() return width, height async def main(): launch_kwargs = { "headless": False } # 啟動瀏覽器 browser = await launch(launch_kwargs) # 打開標簽頁 page = await browser.newPage() # 默認 800 * 600 一般是不夠的 print(page.viewport) # width, height = screen_size() # 設置網頁可視區域大小 await page.setViewport({ "width": width, "height": height }) await browser.close() return asyncio.get_event_loop().run_until_complete(main())
3、導出或加載cookie

# 取出cookie cookies = await page.cookies() # 這里可以做些什么 :) pass # 然后導入cookie await page.setCookie(*cookies)
4、選擇器
讓人極度舒適的一個特性:
使用 page.querySelector如果沒有找到指定的對象,則返回None,而不是拋出異常。不管規范不規范,反正比selenium爽多了。
5、hook
在頁面開始加載前注入js代碼,例如修改掉webdriver屬性,讓天貓檢測不到

# coding:utf8 import asyncio from pyppeteer import launch async def main(): launch_kwargs = { "headless": False } # 啟動瀏覽器 browser = await launch(launch_kwargs) # 打開標簽頁 page = await browser.newPage() page.evaluateOnNewDocument(""" var _navigator = {}; for (name in window.navigator) { if (name != "webdriver") { _navigator[name] = window.navigator[name] } } Object.defineProperty(window, 'navigator', { get: ()=> _navigator, }) """) # page.goto("http://www.tmall.com") await browser.close() return asyncio.get_event_loop().run_until_complete(main())
6、關於各種事件的isTrusted
這個js事件屬性,用js是無法偽造的,但是用pyppeteer發生的各種操作所觸發的事件,是完全真實的,這個歸功於CDP吧。
7、卡死
如果在操作過程中不小心點擊了某個a標簽,導致瀏覽器新打開了一個標簽頁,而你的代碼還在傻乎乎的使用之前的page對象做操作的時候,整個進程就卡住了
沒有超時、沒有異常、就是完全的不知道在干啥
當你把新開的標簽頁手動關閉后,一切就恢復原樣。
tips:
避免這種情況的發生,其實也很簡單,就是在每個可能誤操作點擊導致新開標簽頁的行為后面都強制關閉一下其他標簽頁:
比如:

# 關閉其他標簽頁 for _page in await browser.pages(): if _page != page: _page.close()