今天介绍下如何使用pyppeteer抓取网页的数据。pyppeteer是web应用自动化测试的具,可以直接运行在浏览器中,通过代码控制与页面上元素进行交互,并获取对应的信息。
以前我们我们爬取数据都是通过写代码爬取,当待爬取的网站需要登录时,我们需要在代码中模拟登录;当爬取过快需要验证时,我们需要在代码中实现验证逻辑;当ip被封时,还需要有自己的动态ip库。待爬网站的反爬策略越多,我们爬取的成本就越大。总之,用写代码的方式爬取数据需要构造比较复杂的请求,想尽一切办法将爬虫伪装成真实的用户。
使用pyppeteer这样的工具,就可以在很大程度上解决上面的问题。同时,还有一个优点是所见即所得,不需要再去研究网页复杂的请求结构。当然这类工具也是优缺点的,它增加了你去理解网页上各种元素以及交互的成本。所以我觉得这类工具最适合在短平快的爬虫场景中使用。比如我在最近的工作中就遇到两次这样的情况,想爬一些特别简单的数据来提升工作效率,但又不想研究网页是如何构造请求的,用这种所见即所得的工具就可以快速抓取想要的数据。
下面我们以“抓取百度搜索数据”例子我介绍一下pyppeteer的使用。正式介绍前我们先来看下爬取效果:
安装pyppeteer
python3 -m pip install pyppeteer安装完成后,执行pyppeteer-install命令安装最新版本的 Chromium 浏览器。根据官方文档的说明,安装pyppeteer需要Python3.6以上的版本。
由于pyppeteer是基于asyncio实现的,所以我们的代码中也会用async/await来写代码,之前没写过的朋友也不用担心,基本不影响对pyppeteer的使用,有必要的话以后再单独写篇文章介绍。
首先,用pyppeteer启动 chrome 进程
from pyppeteer import launch # headless 显示浏览器 # --window-size 设置窗体大小 browser = await launch({'headless': False, 'args': ['--window-size=%d,%d' % (width, height)] })然后,打开一个新的标签,并访问百度
# 打开新页面 page = await browser.newPage() # 设置内容显示大小 await page.setViewport({"width": width, "height": height}) # 访问百度 await page.goto('https://www.baidu.com')打开百度网站后,下一步就要向搜索输入框输入内容,首先要找到输入框的html标签
从上图可以看到,<input value="" maxlength="255" autocomplete="off">代码代表搜索输入框,该标签的 class 是s_ipt,那下面我们就通过type函数找到该标签,并键入需要搜索的内容 # 将对应的 selector 填入 python,通过.s_ipt找到输入框html标签 await page.type('.s_ipt', 'python')这里我们搜的是python,有了输入后就可以点击“百度一下”按钮来发起搜索。找按钮的方式与上面一样
可以看到<input type="submit" value="百度一下">代码代表“百度一下”的按钮,该标签的 id 是su,下面就调用click函数找到该标签,并点击 # 通过#su找到“百度一下”按钮html标签 await page.click('#su')这里需要注意su前面是#而不是.,因为在html标签中它用id表示而不是class,这里涉及html selector的内容,不清楚的朋友可以简单补一下。
执行完上面的代码,我们可以看到搜索结果了,调用screenshot方法将当前页面保存
await page.screenshot({'path': 'example.png'})效果如下:
接下来我们就获取网页内容,并解析每条结果 # 获取网页内容 content = await page.content() # 解析 output_search_result(content)通过BeatifulSoup解析每条结果的标题与链接
def output_search_result(html): search_bs = BeautifulSoup(html, 'lxml') all_result = search_bs.find_all("div", {'class': "result c-container"}) for single_res in all_result: title_bs = single_res.find("a") title_url = title_bs.get('href') title_txt = title_bs.get_text() print(title_txt, title_url)输出的内容如下
python官方网站 - Welcome to Python.org ?url=OqtoElo8HW1GdOgAlqdCTz2lpewFLf0HlbnGdyAKD06BfPbw0fsJ_N5fclxx-q1D Python 基础教程 | 菜鸟教程 ?url=IooFgJjdec1qPXhGhF7tur-z2Qt_43RkK3L-9cp8oB-0i2w7unKzLayLjg3zSQeKQieA49JFejMjqTM-TSY3V_ Python3 * 和 ** 运算符_python_极客点儿-CSDN博客 ?url=H3VdAQRAbTkN9jGJGkvhIFTdg48O-b5yib7vCquWyg1-6FZwBVHnJ5iiUYQkjbf-8IuLfOwDXoUMDOdMvXNHkzejts4uRHrczgQqekgQuFy Python教程 - 廖雪峰的官方网站 ?url=piu0nEfXNvkLhWchcdX2EjJvIkQ5beq2_uYH_B7u2vjYO82BZwr8SXgDxnVLZYgGL8xuR_ovjg2cAYfPS9AmLtqUQP-TrWuJWHNqYbxdQnUPTy_VPp8sSBdCaYBl9YDX Python3 教程 | 菜鸟教程 ?url=bx1rMrzxC69Sp0zY08-VhFs40QQ8UFxZdvmZVFcKYkCG2mdojhAMjk5ulKBKwQm77x8vMyOeowW_bNtoP35m3q 你都用 Python 来做什么? - 知乎 ?url=YTMr1ycFjtkWx8lgJ_PT3-kF50vYI6Yibh4o69WL_afBSOkkZmGxexxIKXY3fGAX8X2-AaFbI4jL1vJbKMJrsK Python基础教程,Python入门教程(非常详细) ?url=elAepKY7rhULzTPuwKvk8Cxx21K5D0Ey7-Wj9TZgN49MyasPOXtLYfWbp46QZQie这样,我们的抓取数据的目的已经达到了,当然我们还可以继续拓展下,多用用pyppeteer,比如:我们可以点击下一页,抓取下一页的内容
# next page # 为了点击“下一页”,需要将当前页面滑到底部 dimensions = await page.evaluate('window.scrollTo(0, window.innerHeight)') # 点击“下一页”按钮 await page.click('.n') # 获取第二页的内容 content = await page.content() # 解析 output_search_result(content)操作与之前类似,注释写的也比较清楚,我就不再赘述了。最后可以调用await browser.close()代码关闭浏览器。上述代码可以定义需要定义在一个async函数中,如:
async def main(): # ... 抓取代码然后通过下面代码
asyncio.get_event_loop().run_until_complete(main())调用main函数。
pyppeteer的用法就介绍到这里了,类似的工具还有很多,比如:Selenium,我也试了下,确实如网上所说配置上面需要花些功夫,有兴趣的朋友可以自行尝试。希望今天的内容对你有用。