曾经使用模拟浏览器操作(selenium + webdriver)来写爬虫,但是稍微有点反爬的网站都会对 selenium 和 webdriver 进行识别,网站只需要在前端 js 添加一下判断脚本,很容易就可以判断出是真人访问还是 webdriver 。虽然也可以通过中间代理的方式进行 js 注入屏蔽 webdriver 检测,但是 webdriver 对浏览器的模拟操作(输入、点击等等)都会留下 webdriver 的标记,同样会被识别出来,要绕过这种检测,只有重新编译 webdriver,麻烦自不必说,难度不是一般大。
作为 selenium+webdriver 的优秀替代,pyppeteer 就是一个很好的选择。
pip install pyppeteer
按照官方手册,先来感受一下:
import asyncio
import nest_asyncio
from pyppeteer import launch
nest_asyncio.apply()
async def main():
browser = await launch(headless=False)
page = await browser.newPage()
await page.goto('http://www.baidu.com/')
await browser.close()
asyncio.run(main())
pyppeteer 第一次运行时,会自动下载chromium浏览器,时间可能会有些长。不过,我第一次运行时,直接报错:
[W:pyppeteer.chromium_downloader] start chromium download.
Download may take a few minutes.
--------------------------------------
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)
根据控制台提示进入 pyppeteer.chromium_downloader 模块查看源代码。
从源码中,我们可以看到 downloadURLs、chromiumExecutable 等变量,很明显指的就是下载链接和chromium 的可执行文件路径。我们重点关注一下可执行文件路径。
chromiumExecutable:
chromiumExecutable = {
'linux': DOWNLOADS_FOLDER / REVISION / 'chrome-linux' / 'chrome',
'mac': (DOWNLOADS_FOLDER / REVISION / 'chrome-mac' / 'Chromium.app' /
'Contents' / 'MacOS' / 'Chromium'),
'win32': DOWNLOADS_FOLDER / REVISION / 'chrome-win32' / 'chrome.exe',
'win64': DOWNLOADS_FOLDER / REVISION / 'chrome-win32' / 'chrome.exe',
}
可见,无论在哪个平台下,chromiumExecutable 都是由是4个部分组成,其中 DOWNLOADS_FOLDER 和 REVISION 是定义好的变量:
DOWNLOADS_FOLDER = Path(__pyppeteer_home__) / 'local-chromium'
进一步查看可以发现:
__pyppeteer_home__ = os.environ.get('PYPPETEER_HOME', AppDirs('pyppeteer').user_data_dir)
REVISION = os.environ.get('PYPPETEER_CHROMIUM_REVISION', __chromium_revision__)
所以,DOWNLOADS_FOLDER 和 REVISION都是读取对应环境变量设置好的值,如果没有设置,就使用默认值。我们来输出一下,看看默认值:
import pyppeteer.chromium_downloader
print('默认版本是:{}'.format(pyppeteer.__chromium_revision__))
print('可执行文件默认路径:{}'.format(pyppeteer.chromium_downloader.chromiumExecutable.get('win64')))
print('win64平台下载链接为:{}'.format(pyppeteer.chromium_downloader.downloadURLs.get('win64')))
输出结果如下:
默认版本是:588429
可执行文件默认路径:C:\Users\wuzhiyao\AppData\Local\pyppeteer\pyppeteer\local-chromium\588429\chrome-win32\chrome.exe
win64平台下载链接为:https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/588429/chrome-win32.zip
在使用上面代码的时候,你可以将win64换成你的平台就好了。先去下载链接下载好chrome-win32.zip文件,然后解压,内容如下:
我们可以通过配置环境变量改这一部分(或者也可以直接改源码,读取环境变量那一行,直接设为固定值),通过os.environ添加PYPPETEER_HOME这一变量值,例如我的chromium位置为D:\opensource\local-chromium\588429\chrome-win32(版本号和之前输出的要对应),根据源码中
DOWNLOADS_FOLDER = Path(__pyppeteer_home__) / 'local-chromium'
在环境变量里增加值:PYPPETEER_HOME = D:\opensource
完成操作后重启系统,在运行下代码可见变化:
import pyppeteer.chromium_downloader
print('默认版本是:{}'.format(pyppeteer.__chromium_revision__))
print('可执行文件默认路径:{}'.format(pyppeteer.chromium_downloader.chromiumExecutable.get('win64')))
print('win64平台下载链接为:{}'.format(pyppeteer.chromium_downloader.downloadURLs.get('win64')))
--------------------------------
默认版本是:588429
可执行文件默认路径:D:\opensource\local-chromium\588429\chrome-win32\chrome.exe
win64平台下载链接为:https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/588429/chrome-win32.zip
测试代码也能正常运行:
import asyncio
import nest_asyncio
from pyppeteer import launch
nest_asyncio.apply()
async def main():
browser = await launch(headless=False)
page = await browser.newPage()
await page.goto('http://www.baidu.com/')
#await browser.close()
asyncio.run(main())
原文参考:
https://blog.csdn.net/qq_33254766/article/details/109139378