1.安装
pip3.6 install pyppeteer==0.2.2 -i https://mirrors.aliyun.com/pypi/simple pyppeteer-install.exe # 安装 chromium 浏览器到 pyppeteer 的默认位置
2.用法 https://miyakogi.github.io/pyppeteer/reference.html 文档说明
pyppeteer-install 第一次运行pyppeteer时,它将下载最新版本的Chromium
3.简单用法
import asyncio import logging import os import time import tkinter from lxml import etree from pyppeteer import launch BASE_DIR = os.path.dirname(os.path.abspath(__file__)) logging.basicConfig( level=logging.INFO, # 定义输出到文件的log级别,大于此级别的都被输出 format='%(asctime)s %(filename)s %(levelname)s : %(message)s', # 定义输出log的格式 datefmt='%Y-%m-%d %H:%M:%S', # 时间 filename="{}/qimai_downloads.log".format(BASE_DIR), filemode='a') # 写入模式“w”或“a” console = logging.StreamHandler() console.setLevel(logging.INFO) # 设置格式 formatter = logging.Formatter('%(asctime)s %(filename)s %(levelname)s : %(message)s') # 告诉handler使用这个格式 console.setFormatter(formatter) # 为root logger添加handler logging.getLogger('').addHandler(console) class pyppeteerDome(object): async def intercept_request(self, req): """请求过滤""" if req.resourceType in ['image', 'media', 'eventsource', 'websocket']: await req.abort() else: await req.continue_() async def intercept_response(self, res): """结果过滤""" resourceType = res.request.resourceType if resourceType in ['xhr', 'fetch']: resp = await res.text() print(resp) def screen_size(self): tk = tkinter.Tk() width = tk.winfo_screenwidth() height = tk.winfo_screenheight() tk.quit() return width, height async def main(self): self.browser = await launch(ignoreHTTPSErrors=False, headless=False, dumpio=True, autoClose=False, userDataDir="", args=['--no-sandbox', '--window-size=1920,1080', '--disable-infobars', '--disable-extensions', '--hide-scrollbars', '--disable-bundled-ppapi-flash', '--mute-audio', '--disable-setuid-sandbox', '--disable-gpu', '--log-level=3', '--proxy-server=http://127.0.0.1:8008']) # 进入有头模式 # ignoreHTTPSErrors=False # 是否忽略HTTPS错误。默认为 False # headless=False # 是否以无头模式运行浏览器 # executablePath (str): 可执行文件的路径,如果指定之后就不需要使用默认的 Chromium 了,可以指定为已有的 Chrome 或 Chromium # slowMo (int|float): 通过传入指定的时间,可以减缓 Pyppeteer 的一些模拟操作。 # args (List[str]): 在执行过程中可以传入的额外参数。 # ignoreDefaultArgs (bool): 不使用 Pyppeteer 的默认参数,如果使用了这个参数,那么最好通过 args 参数来设定一些参数,否则可能会出现一些意想不到的问题。这个参数相对比较危险,慎用。 # handleSIGINT (bool): 是否响应 SIGINT 信号,也就是可以使用 Ctrl + C 来终止浏览器程序,默认是 True。 # handleSIGTERM (bool): 是否响应 SIGTERM 信号,一般是 kill 命令,默认是 True。 # handleSIGHUP (bool): 是否响应 SIGHUP 信号,即挂起信号,比如终端退出操作,默认是 True。 # dumpio (bool): 是否将 Pyppeteer 的输出内容传给 process.stdout 和 process.stderr 对象,默认是 False。 # userDataDir (str): 即用户数据文件夹,即可以保留一些个性化配置和操作记录。(比如登录信息等;可以在以后打开时自动登录;) # env (dict): 环境变量,可以通过字典形式传入。 # devtools (bool): 是否为每一个页面自动开启调试工具,默认是 False。如果这个参数设置为 True,那么 headless 参数就会无效,会被强制设置为 False。 # logLevel (int|str): 日志级别,默认和 root logger 对象的级别相同。 # autoClose (bool): 当一些命令执行完之后,是否自动关闭浏览器,默认是 True。 # --proxy-server=http://127.0.0.1:8008 代理 # --start-maximized 最大化窗口 # --no-sandbox 取消沙盒模式 沙盒模式下权限太小 # --disable-infobars 不显示信息栏 比如 chrome正在受到自动测试软件的控制 # --log-level=3 log等级设置 在某些不是那么完整的系统里 如果使用默认的日志等级 可能会出现一大堆的warning信息 # --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 设置UA # "userDataDir": "/root" 用户数据保存目录 这个最好也自己指定一个目录 self.page.on('request', self.intercept_request) self.page.on('response', self.intercept_response) self.page = await self.browser.newPage() # 打开新的标签页 await self.page.reload() # 获取当前操作的界面重新加载 await self.page.goBack() # 当前操作界面返回 width, height = self.screen_size() await self.page.setViewport({'width': width, 'height': height}) # 设置页面视图大小 await self.page.setRequestInterception(True) await self.page.setUserAgent("Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5") # 设置浏览器头 await self.page.setJavaScriptEnabled(enabled=True) # 是否启用JS,enabled设为False,则无渲染效果 await self.page.evaluate('window.scrollBy(0, document.body.scrollHeight)') # 滑动到当前界面底部 # await self.page.setCookie(*cookies) # 设置cookie # evaluate()是执行js的方法,js逆向时如果需要在浏览器环境下执行js代码的话可以利用这个方法 临时修改浏览器属性中的 webdriver 属性 # await page.evaluate('''() =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => false } }) }''') # 将一段 js 代码加载到页面文档中,当发生页面导航、页面内嵌框架导航的时候加载的 js 代码会自动执行,那么当页面刷新的时候该 js 也会执行,这样就保证了修改网站的属性持久化的目的 await self.page.evaluateOnNewDocument('''() =>{ Object.defineProperties(navigator,{ webdriver:{ get: () => false } }) }''') # 访问的网站 time.sleep(2) # 等待 # 访问主页 timeout:超时时间 res = await self.page.goto('http://news.baidu.com/', options={'timeout': 100000}) await asyncio.sleep(2) # 等待 print("resp_url:{}".format(self.page.url)) # url print("resp_headers:{}".format(res.headers)) # 响应头 print("resp_status:{}".format(res.status)) # 响应状态 print("cookies:{}".format(await self.page.cookies())) # 打印页面cookies print("title:{}".format(await self.page.title())) # 打印当前页标题 print("content:{}".format(await self.page.content())) # 获取所有 html 内容 await self.page.screenshot({'path': './qimai.jpg'}) # 截图保存路径 await self.page.pdf({"path": "./qimai.pdf", "format": 'A4'}) # 保存 PDF content = etree.HTML(await self.page.content()) data = content.xpath('')[0].strip().replace(':', '') elements = await self.page.xpath('//*[@id="pane-news"]/div/ul/li/strong/a/@href') print("*" * 200) print("elements:{}".format(elements)) for i in elements: print(i) await self.page.type(data, "176823035") # 向输入框输入数据 await self.page.click(data) # 鼠标单击某一个元素 await self.page.evaluate(data) # 清空某个input的值 pages = await self.browser.pages() # 获取浏览器打开了几个界面对象 pages[-1] # 获取当前浏览器打开的【最后一个】界面对象 self.page.frames # 获取当前界面中所有的frame对象 time.sleep(1000) # 等待 await self.page.close() # 关闭浏览器 if __name__ == "__main__": dome = pyppeteerDome() asyncio.get_event_loop().run_until_complete(dome.main()) # 调用
4.获取response和request对象
import asyncio import requests from pyppeteer import launch from pyppeteer_stealth import stealth requests.packages.urllib3.disable_warnings() async def interceptResponse(response): print("printing response") print(response) print(response.url) print(response.headers) print(response.status) print(response.request) # 同interceptRequest(request)的request对象 return response.headers async def interceptRequest(request): print("printing request") print(request) print(request.url) print(request.headers) print(request.method) print(request.postData) return request.headers async def get_web_html(url): # browser = await launch(headless=True, ignoreHTTPSErrors=True, userDataDir='userdata', dumpio=True, args=['--disable-infobars', "--start-maximized", "--no-sandbox"], ignoreDefaultArgs=['--enable-automation']) browser = await launch(headless=True, args=['--disable-infobars', "--no-sandbox"]) web = await browser.createIncognitoBrowserContext() page = await web.newPage() request_data = page.on('request', lambda request: asyncio.ensure_future(interceptRequest(request))) print("request_data:{}".format(request_data)) print("*" * 100) response_data = page.on('response', lambda response: asyncio.ensure_future(interceptResponse(response))) print('response_data:{}'.format(response_data)) print("-" * 100) await page.setViewport({'width': 1920, 'height': 1080}) # 设置页面视图大小 await page.setUserAgent("Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5") # 设置浏览器头 await stealth(page) await page.goto(url) await asyncio.sleep(1) doc = await page.content() await browser.close() return doc def reque_url(url): html = asyncio.get_event_loop().run_until_complete(get_web_html(url)) return html if __name__ == '__main__': reque_url("https://www.baidu.com/", )
import asyncio import logging from pyppeteer import launch from pyppeteer_stealth import stealth retry_num = 3 async def get_cookie(url1): for _ in range(retry_num): proxies = get_proxies() browser = await launch( { 'headless': True, # 关闭无头模式 'args': [ '--proxy-server={}'.format(proxies.get('http', '').replace('http://', '')), '--no-sandbox', ], 'dumpio': False, } ) try: page = await browser.newPage() await stealth(page) await page.setViewport({'width': 1920, 'height': 1080}) await asyncio.wait_for(page.goto(url=url1, options={'timeout': 6000}), timeout=6) await page.screenshot({'path': '1.png'}) cookie = await page.cookies() await browser.close() results = cookie if results: new_cookie = '' for cookie in results: new_cookie = new_cookie + '{}={};'.format(cookie['name'], cookie['value']) return new_cookie else: return '' except Exception as e: await browser.close() logging.error('浏览器异常 {}'.format(_)) if _ == retry_num - 1: logging.error('浏览器异常: {}'.format(_)) return '' def cookie_main(url): cookie = asyncio.get_event_loop().run_until_complete(get_cookie(url)) return cookie print(cookie_main("http://sthj.gansu.gov.cn/sthj/c113046/xxgk_list.shtml"))