今天介绍下如何使用pyppeteer
抓取网页的数据。pyppeteer
是web应用自动化测试的具,可以直接运行在浏览器中,通过代码控制与页面上元素进行交互,并获取对应的信息。
以前我们我们爬取数据都是通过写代码爬取,当待爬取的网站需要登录时,我们需要在代码中模拟登录;当爬取过快需要验证时,我们需要在代码中实现验证逻辑;当ip被封时,还需要有自己的动态ip库。待爬网站的反爬策略越多,我们爬取的成本就越大。总之,用写代码的方式爬取数据需要构造比较复杂的请求,想尽一切办法将爬虫伪装成真实的用户。
使用pyppeteer
这样的工具,就可以在很大程度上解决上面的问题。同时,还有一个优点是所见即所得,不需要再去研究网页复杂的请求结构。当然这类工具也是优缺点的,它增加了你去理解网页上各种元素以及交互的成本。所以我觉得这类工具最适合在短平快的爬虫场景中使用。比如我在最近的工作中就遇到两次这样的情况,想爬一些特别简单的数据来提升工作效率,但又不想研究网页是如何构造请求的,用这种所见即所得的工具就可以快速抓取想要的数据。
下面我们以“抓取百度搜索数据”例子我介绍一下pyppeteer
的使用。正式介绍前我们先来看下爬取效果:
安装pyppeteer
python3 -m pip install pyppeteer
复制代码
安装完成后,执行pyppeteer-install
命令安装最新版本的 Chromium 浏览器。根据官方文档的说明,安装pyppeteer
需要Python
3.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 id="kw" name="wd" class="s_ipt" value="" maxlength="255" autocomplete="off">
代码代表搜索输入框,该标签的 class 是s_ipt
,那下面我们就通过type
函数找到该标签,并键入需要搜索的内容
# 将对应的 selector 填入 python,通过.s_ipt找到输入框html标签
await page.type('.s_ipt', 'python') 复制代码
这里我们搜的是python,有了输入后就可以点击“百度一下”按钮来发起搜索。找按钮的方式与上面一样 可以看到<input type="submit" id="su" value="百度一下" class="bg s_btn">
代码代表“百度一下”的按钮,该标签的 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 http://www.baidu.com/link?url=OqtoElo8HW1GdOgAlqdCTz2lpewFLf0HlbnGdyAKD06BfPbw0fsJ_N5fclxx-q1D
Python 基础教程 | 菜鸟教程 http://www.baidu.com/link?url=IooFgJjdec1qPXhGhF7tur-z2Qt_43RkK3L-9cp8oB-0i2w7unKzLayLjg3zSQeKQieA49JFejMjqTM-TSY3V_ Python3 * 和 ** 运算符_python_极客点儿-CSDN博客 http://www.baidu.com/link?url=H3VdAQRAbTkN9jGJGkvhIFTdg48O-b5yib7vCquWyg1-6FZwBVHnJ5iiUYQkjbf-8IuLfOwDXoUMDOdMvXNHkzejts4uRHrczgQqekgQuFy Python教程 - 廖雪峰的官方网站 http://www.baidu.com/link?url=piu0nEfXNvkLhWchcdX2EjJvIkQ5beq2_uYH_B7u2vjYO82BZwr8SXgDxnVLZYgGL8xuR_ovjg2cAYfPS9AmLtqUQP-TrWuJWHNqYbxdQnUPTy_VPp8sSBdCaYBl9YDX Python3 教程 | 菜鸟教程 http://www.baidu.com/link?url=bx1rMrzxC69Sp0zY08-VhFs40QQ8UFxZdvmZVFcKYkCG2mdojhAMjk5ulKBKwQm77x8vMyOeowW_bNtoP35m3q 你都用 Python 来做什么? - 知乎 http://www.baidu.com/link?url=YTMr1ycFjtkWx8lgJ_PT3-kF50vYI6Yibh4o69WL_afBSOkkZmGxexxIKXY3fGAX8X2-AaFbI4jL1vJbKMJrsK Python基础教程,Python入门教程(非常详细) http://www.baidu.com/link?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,我也试了下,确实如网上所说配置上面需要花些功夫,有兴趣的朋友可以自行尝试。希望今天的内容对你有用。
欢迎公众号「渡码」,输出别地儿看不到的干货。回复关键字 爬虫 获取完整源码
评论前必须登录!
注册