直接上干貨
注入攔截和篩選請(qǐng)求和返回
下面這個(gè)例子經(jīng)常用來(lái):
- 加快網(wǎng)頁(yè)加載速度
- 快速篩選數(shù)據(jù)api接口
做新聞爬蟲(chóng)的時(shí)候凳宙,遇到網(wǎng)頁(yè)有視頻其實(shí)挺尷尬的片吊,首先如果加載視頻會(huì)導(dǎo)致打開(kāi)網(wǎng)頁(yè)比較慢超营,有時(shí)甚至?xí)?dǎo)致瀏覽器超時(shí)崩潰,其次是視頻的加載可能不同時(shí)帶入一些廣告的超鏈接喻频,對(duì)于提取新聞內(nèi)容會(huì)造成干擾。
通過(guò)page.setRequestInterception參數(shù)開(kāi)啟注入肘迎。
先上整體代碼
import asyncio
from pyppeteer import launch
async def inject_request(req):
"""
resourceType:
document, stylesheet, image, media, font, script, texttrack,
xhr, fetch, eventsource, websocket, manifest, other
"""
if req.resourceType in ['media','image']:
await req.abort()
else:
await req.continue_()
async def inject_response(res):
if res.request.resourceType in ['xhr']:
print(res.request.url)
async def main():
browser = await launch({'headless':False})
page = await browser.newPage()
await page.setRequestInterception(True)
page.on('request', inject_request)
page.on('response',inject_response)
await page.goto('https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0')
await page.waitFor(5 * 1000)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
先分析inject_request部分甥温,
async def inject_request(req):
if req.resourceType in ['media','image']:
await req.abort()
else:
await req.continue_()
一般用得比較多的是一個(gè)屬性?xún)蓚€(gè)方法,
一個(gè)屬性:
resourceType,表示請(qǐng)求的資源類(lèi)型妓布,有document, stylesheet, image, media, font, script, texttrack, xhr, fetch, eventsource, websocket, manifest, other(加粗的是比較常用的資源類(lèi)型)
兩個(gè)方法:
abort(),跳過(guò)當(dāng)前請(qǐng)求
continue_(),繼續(xù)當(dāng)前請(qǐng)求
上面代碼段意思是姻蚓,不請(qǐng)求圖片和媒體資源。
inject_response部分
async def inject_response(res):
if res.request.resourceType in ['xhr']:
print(res.request.url)
一般js動(dòng)態(tài)加載的數(shù)據(jù)連接在xhr資源秋茫,所以我這里把網(wǎng)頁(yè)請(qǐng)求的xhr資源都打印出來(lái)史简,如果這里沒(méi)有數(shù)據(jù)連接,那就是在document里面了肛著,比F12清晰一點(diǎn)圆兵。
注入js
以淘寶登陸驗(yàn)證碼為例
淘寶的驗(yàn)證碼驗(yàn)證模塊會(huì)檢測(cè)瀏覽器環(huán)境,主要是檢測(cè)
window.navigator.webdriver
參數(shù)枢贿,如果是瀏覽器直接打開(kāi)殉农,如下圖:如果是使用webdriver驅(qū)動(dòng)打開(kāi)(selenium,puppeteer,pyppeteer),這個(gè)參數(shù)如下圖:
嘗試直接覆蓋這個(gè)屬性,但是沒(méi)有效果局荚。
通過(guò)查資料超凳,發(fā)現(xiàn)
Object.defineProperty()
方法會(huì)直接在一個(gè)對(duì)象上定義一個(gè)新屬性,或者修改一個(gè)對(duì)象的現(xiàn)有屬性耀态, 并返回這個(gè)對(duì)象轮傍。如果不指定configurable, writable, enumerable ,則這些屬性默認(rèn)值為false首装,如果不指定value, get, set创夜,則這些屬性默認(rèn)值為undefined
完整代碼
import asyncio
import random
from pyppeteer import launch
def input_time_random():
return random.randint(100, 151)
async def main():
browser = await launch({'headless':False})
page = await browser.newPage()
await page.evaluateOnNewDocument(
'''() =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => false } }) }''')
await page.evaluateOnNewDocument('''() =>{ window.navigator.chrome = { runtime: {}, }; }''')
await page.evaluateOnNewDocument('''() =>{ Object.defineProperty(navigator, 'languages', { get: () => ['en-US', 'en'] }); }''')
await page.evaluateOnNewDocument('''() =>{ Object.defineProperty(navigator, 'plugins', { get: () => [1, 2, 3, 4, 5,6], }); }''')
await page.goto('https://login.taobao.com')
await page.waitFor(4 * 1000)
await page.click('#J_QRCodeLogin > div.login-links > a.forget-pwd.J_Quick2Static')
await page.waitFor(3 * 1000)
await page.type('#TPL_username_1', '123123', {'delay': input_time_random() - 50})
await page.type('#TPL_password_1', '232322332', {'delay': input_time_random()})
await page.waitFor(2 * 1000)
el = await page.querySelector('#nc_1_n1z')
box = await el.boundingBox()
await page.hover('#nc_1_n1z')
await page.mouse.down()
await page.mouse.move(box['x']+1000,box['y'], {'delay': random.randint(1000, 2000),'steps':3})
await page.mouse.up()
await page.waitFor(5 * 1000)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())