カスタムJSスクリプトを実行する
Pyppeteer Pageオブジェクトは一連の評価メソッドを提供します。これらのメソッドを使用して、いくつかのカスタムJSコードを実行でき、主に次の3つのAPIを提供します。
(1)page.evaluate(pageFunction [、... args])、pageFunctionの実行結果を返します。pageFunctionはページで実行される関数または式を表し、argsはpageFunctionに渡されるパラメーターを表します
例:
await page.goto('https://www.baidu.com')
# 输出字符串
await page.evaluate('alert("在浏览器执行js脚本!")')
# 将元素作为参数传入 page.evaluate
element = await page.J('#ul>a[name="tj_trtieba"]')
print(await page.evaluate('el => el.innerHTML', element))
print(await page.evaluate('el => el.href', element)
# 执行函数
el = await page.evaluate('() => document.querySelector("#su").value')
print(el)
(2)page.evaluateHandle(pageFunction [、... args])、このメソッドとpage.evaluateの唯一の違いは、このメソッドがページタイプ(JSHandle)を返すことです
例:
await page.goto('https://www.baidu.com')
el = await page.evaluateHandle('() => document.querySelector("#su").value')
print(type(el))
print(el.toString())
(3)page.evaluateOnNewDocument(pageFunction [、... args])。指定された関数は、それが属するページが作成され、それが属するページのスクリプトが実行される前に呼び出されます。多くの場合、ページのJS環境を変更するために使用されます。
以下は、中間JSの挿入と、Taobaoがブラウザーを検出するために呼び出すJSを変更した結果です。
import asyncio
from pyppeteer import launch
async def main():
browser = await launch({
'headless': False,
'args': ['--no-sandbox', '--window-size=1366,768']
})
page = await browser.newPage()
await page.setViewPort({'width': 1366, 'height': 768})
await page.evaluateOnNewDocument('''() => {
Object.defineProperty(navigator, 'webdriver', {get: () => false });
}''')
await page.goto('https://login.taobao.com')
await page.evaluate('alert(navigator.webdriver)')
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
元素操作
ElementHandleは、ページ内のDOM要素を表します。page.querySelector()メソッドを使用して作成できます。DOM要素には、ページと同じメソッドがいくつかあります:J()、JJ()、Jeval()、JJeval()、screenshot()、type()、click()、tap()。さらに、いくつかの便利な方法があります。
(1)要素の境界ボックスの座標を取得します:boundingBox()、要素の境界ボックスを返します(メインフレームに対して)=> x座標、y座標、幅、高さ
(2)要素は表示されていますか:isIntersectingViewport()
(3)ファイルをアップロード:uploadFile(* filepaths)
(4)ElementHandleクラスはFrameクラスに変換されます:contentFrame()、ハンドルがiframeを参照しない場合、Noneを返します。
(5)要素にフォーカスします:focus()
(6)マウスに関連:hover()、要素の上にマウスを置きます
(7)キーボードに関連:press(key [、options])、key、keyはキーの名前を表し、オプションを設定できます:
- text(string)-指定した場合、このテキストを使用して入力イベントを生成します
- delay(number)-キーダウンとキーアップの間の待機時間、デフォルトは0
鼠标事件
Mouseクラスは、ビューポートの左上隅を基準にしたメインフレームのCSSピクセルで動作します。
(1)page.mouse.down([options])マウスを押すと、オプションを構成できます。
- button(str)どのキーが押されたか、オプションの値は[左、右、中央]、デフォルトは左、つまり左マウスボタン
- clickCount(int)プレス、クリック、ダブルクリックなどの回数
(2)page.mouse.up([options])マウスを離します。オプションは上記と同じです
(3)page.mouse.move(x、y、[options])マウスを指定された位置に移動し、options.stepsは移動のステップ長を表します
(4)page.mouse.click(x、y、[options])指定された位置でのマウスクリック、これは実際にはmouse.moveとmouse.downまたはmouse.upのショートカット操作です
模拟登录的验证码处理
可能用到的方法:
ElementHandle.boundingBox()、ElementHandle.hover()
mouse.down()、mouse.move()、mouse.up()、mouse.click()
例1:Taobao確認コードのスライダーをドラッグする
(1)淘宝網の検証コード検証モジュールがブラウザー環境を検出し、JSを挿入します。
(2)可能な限りユーザー操作をシミュレートします。乱数はPyppeteerの実行速度を遅くします。
例:
import asyncio
import random
from pyppeteer import launch
async def main():
browser = await launch({
'headless': False,
'args': ['--no-sandbox', '--window-size=1366,768']
})
page = await browser.newPage()
await page.setViewport({'width': 1366, 'height': 768})
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 asyncio.sleep(2)
try:
await page.click('div.login-links > a.forget-pwd.J_Quick2Static')
except:
pass
await asyncio.sleep(2)
await page.type('#TPL_username_1', '123123123', {'delay': random.randint(60, 121)})
await page.type('#TPL_password_1', '1234567890', {'delay': random.randint(100, 151)})
await asyncio.sleep(1.5)
try:
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'] + random.randint(333, 999), box['y'], {'steps': 5})
await page.mouse.up()
except:
pass
await asyncio.sleep(1.8)
await page.click('#J_SubmitStatic')
await asyncio.sleep(5)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
例2:鉄道12306タッチ検証コード
(1)12306の検証コードを分析します。これは次のようになります。
マウスクリックの位置を各画像の中心点にすることができます。
この値は次のように計算できます。
- 幅:37、37 * 3、37 * 5、37 * 7; 即37、111、185、259
- 高さ(0):70
- 高さ(1):70 +(190-30)/ 2、つまり150
検証コード画像の座標がx、yの場合、2番目と7番目の画像の位置は、(x + 111、y + 70)、(x + 185、y + 150)として表すことができます。
例:
import asyncio
import random
from pyppeteer import launch
async def main():
browser = await launch({
'headless': False,
'args': [f'--window-size=1366,768', '--no-sandbox']
})
page = await browser.newPage()
await page.goto('https://kyfw.12306.cn/otn/login/init',
{'waitUntil': 'networkidle0'})
await page.setViewport({'width': 1366, 'height': 768})
# 等待验证码加载
code = await page.waitForFunction(
'''() => document.querySelector("img.touclick-image")''')
# 验证码截图
await code.screenshot({'path': 'code.png'})
# 获取验证码坐标
box = await code.boundingBox()
await page.waitFor(2 * 1000)
# 点击第2张图片
await page.mouse.click(box['x']+111, box['y']+70)
await page.waitFor(random.randint(567, 3456))
# 点击第7张图片
await page.mouse.click(box['x']+185, box['y'] + 150)
await page.waitFor(3 * 1000)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
(2)コーディングプラットフォーム:12306
確認コードの認識は少し人間味がありません;コーディングプラットフォームとのドッキングはより良い選択です;原則はバイトで確認コード画像を送信し、文字列を返すこと183,68|193,161
です。
Super EagleコーディングプラットフォームAPI:
chaojiying.py
#!/usr/bin/env python
# coding:utf-8
import requests
from hashlib import md5
class CodeInfo(object):
def __init__(self):
self.username = '用户名'
self.password = md5('密码'.encode('utf8')).hexdigest()
self.soft_id = '96001' # 用户中心 >> 软件ID,生成一个替换96001
self.base_params = {
'user': self.username,
'pass2': self.password,
'softid': self.soft_id,
}
self.headers = {
'Connection': 'Keep-Alive',
'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
}
def process(self, im, codetype):
url = 'http://upload.chaojiying.net/Upload/Processing.php'
params = {'codetype': codetype}
params.update(self.base_params)
files = {'userfile': ('ccc.jpg', im)}
r = requests.post(url, data=params, files=files, headers=self.headers)
return r.json()
def report(self, im_id):
"""
im_id:报错题目的图片ID
"""
url = 'http://upload.chaojiying.net/Upload/ReportError.php'
params = {'id': im_id}
params.update(self.base_params)
r = requests.post(url, data=params, headers=self.headers)
return r.json()
if __name__ == '__main__':
im = open('code.png', 'rb').read()
"""
9004 验证码类型
参考 http://www.chaojiying.com/price.html
"""
answer = CodeInfo().process(im, 9004)
print(answer)
ログイン例12306
import asyncio
import random
from pyppeteer import launch
from chaojiying import CodeInfo
def pic_info():
im = open('code.png', 'rb').read()
answer = CodeInfo().process(im, 9004)
print(answer)
return answer['pic_str']
async def main():
browser = await launch({
'headless': False,
'args': ['--window-size=1366,768', '--no-sandbox']
})
page = await browser.newPage()
await page.goto('https://kyfw.12306.cn/otn/login/init',
{'waitUntil': 'networkidle0'})
await page.setViewport({'width': 1366, 'height': 768})
code =await page.waitForFunction(
'''() => document.querySelector("img.touclick-image")''')
await code.screenshot({'path': 'code.png'})
await page.waitFor(2 * 1000)
await page.type('#username', '[email protected]',
{'delay': random.randint(60, 121)})
await page.waitFor(random.randint(345, 1234))
await page.type('#password', '1234567890',
{'delay': random.randint(100, 151)})
pic_str = pic_info()
points = list(set(pic_str.split('|')))
box = await code.boundingBox()
for point in points:
p = point.split(',')
await page.mouse.click(box['x']+int(p[0]), box['y']+int(p[1]))
await page.waitFor(random.randint(567, 3456))
await page.click('#loginSub')
await page.waitFor(5 * 1000)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
键盘事件
キーボードは、仮想キーボードを管理するためのインターフェースを提供します。高度なインターフェースはkeyboard.typeで、元の文字を受け取り、ページ上で対応するkeydown、keypress / input、keyupイベントを生成します。
より細かい制御(仮想キーボード)を行うには、keyboard.down、keyboard.up、およびkeyboard.sendCharacterを使用して、イベントが実際のキーボードによって生成されたかのように、手動でイベントをトリガーできます。
キーボードのいくつかのAPIは次のとおりです。
- keyboard.down(key [、options])はkeydownイベントをトリガーします
- keyboard.press(key [、options])キーを押すと、キーは左側の「ArrowLeft」などのキーの名前を表します。
- keyboard.sendCharacter(char)文字を入力してください
- keyboard.type(text、options)文字列を入力してください
- keyboard.up(key)はkeyupイベントをトリガーします
いくつかの文字列を選択して例を削除するには、Shiftキーを押し続けます。
import asyncio
from pyppeteer import launch
async def main():
browser = await launch({'headless': False})
page = await browser.newPage()
await page.goto('https://www.baidu.com', {'waitUntil': 'networkidle0'})
el = await page.J('#kw')
await el.focus()
await page.keyboard.type('Hello, World!')
await page.keyboard.press('ArrowLeft')
await page.keyboard.down('Shift')
for _ in ' World':
await page.keyboard.press('ArrowLeft')
await page.keyboard.press('ArrowLeft')
await page.keyboard.up('Shift')
await page.keyboard.press('Backspcae')
# 结果字符串最终为'Hello!'
await asyncio.sleep(5)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
押された A
例:
await page.keyboard.down('Shift')
await page.keyboard.press('KeyA')
await page.keyboard.up('Shift')
詳細なヘルス名のマッピングは、ソースコードで確認できます。
Lib \ site-packages \ pyppeteer \ us_keyboard_layout.py
内嵌框架
Page.frames、ElementHandle.contentFrameメソッドを介して取得でき、同時にページを持つ複数のメソッドがあります。
**その他:
- childFramesは子フレームを取得し、リストを返します
- parentFrameは親フレームを返します
- content()はフレームのHTMLコンテンツを返します
- url get url
- 名前は名前を取得します
- title()タイトルを取得します
例:
import asyncio
from pyppeteer import launch
async def main():
browser = await launch({'headless': False})
page = await browser.newPage()
await page.goto('http://www.4399.com', {'waitUntil': 'networkidle0'})
await page.click('#login_tologin')
await asyncio.sleep(1)
frame = page.frames[1]
await frame.type('#username', '123456789')
await frame.type('#j-password', '998765433')
await asyncio.sleep(5)
await browser.close()
asyncio.get_event_loop().run_until_complete(main())
または:
await page.click('#login_tologin')
await asyncio.sleep(1)
element = await page.J('iframe')
frame = await element.contentFrame()