网络是一个庞大而强大的数据库,每天都有大量数据产生。随着大数据和数据科学的兴起,数据变得比以往更有用,用于训练机器学习算法、洞察未来、预测等目的。
手动逐页提取数据是缓慢且耗时的。网页爬取是一个解决方案,能以编程方式从网络中提取数据。通过浏览器自动化,模拟人类动作如点击和滚动,用户可以高效地收集有用的数据,免去手工操作的繁琐。
在Python中,有多种用于网页爬取的工具和库,包括request、BeautifulSoup、Scrapy、MechanicalSoup、lxml和selenium。本文将介绍另一个强大的选择——Pyppeteer,并探索作为Python开发者如何使用它。
什么是Pyppeteer? Pyppeteer是JavaScript(Node)库Puppeteer的Python封装。它类似于Selenium,支持无头模式,但Pyppeteer本地支持仅限于JavaScript和Chromium浏览器。
无头模式指在无图形用户界面(GUI)的背景下运行网络浏览器。适用于网络自动化、自动测试和网络爬取,大大减少了加载时间和计算需求,一切在后台完成。
为什么选择Pyppeteer? 虽然像request和BeautifulSoup这样的工具适用于静态网站,但对于动态或反应式网站,如ReactJS、AngularJS或VueJS,它们无法处理动态生成的内容。
Pyppeteer提供对整个浏览器及其元素的控制,不同于使用HTTP库如request获取页面内容。这提供更大的灵活性和功能。Pyppeteer适用于屏幕截图、表单提交、自动化UI测试、抓取单页应用程序生成预渲染内容(服务器端渲染),以及在更新的Chrome和JavaScript版本中运行测试等。
实现Pyppeteer 现在你了解了Pyppeteer,让我们开始学习在Python中如何实现它。
首先,最好的做法是为开发环境创建独立的虚拟环境,避免干扰现有库。
pip install –upgrade virtualenv
pip3 install –upgrade virtualenv
virtualenv pyp-env
pyp-env\Scripts\activate
source pyp-env/bin/activate
安装 Pyppeteer是需要安装的主要依赖项。注意,它要求你运行Python 3.6以上,你可以直接使用pip或从Pyppeteer GitHub仓库安装。
C:> python -m pip install pyppeteer
$ python3 -m pip install pyppeteer
C:> python -m pip install -U git+https://github.com/miyakogi/pyppeteer.git@dev
$ python3 -m pip install -U git+https://github.com/miyakogi/pyppeteer.git@dev
请注意:
$ pyppeteer-install
值得一提的是,Pyppeteer默认有异步支持,这意味着它允许你的脚本/应用程序异步处理浏览器自动化和刮擦过程。当涉及到HTTP调用的任务时,这可能是一个性能提升器。
用Pyppeteer抓取截图 接下来,你将学习如何使用Pyppeteer从网站上捕捉屏幕截图,并将其保存为图片。
首先,导入你所需要的库:
import asyncio
from pyppeteer import launch
然后创建一个异步函数来打开一个网站,并捕获一个屏幕截图:
import asyncio
from pyppeteer import launch
async def main():
# launch chromium browser in the background
browser = await launch()
# open a new tab in the browser
page = await browser.newPage()
# add URL to a new page and then open it
await page.goto(“https://www.python.org/”)
# create a screenshot of the page and save it
await page.screenshot({“path”: “python.png”})
# close the browser
await browser.close()
print(“Starting…”)
asyncio.get_event_loop().run_until_complete(main())
print(“Screenshot has been taken”)
最后,运行你的脚本(app.py):
C:> python app.py
……
Starting…
Screenshot has been taken
$ python3 app.py
……
Starting…
Screenshot has been taken 当你看到 “屏幕截图已被拍摄 “时,你应该能够在你的当前目录中看到一个名为 “python.png “的新图像。它看起来应该是这样的:
这是一个简单的使用Pyppeteer进行屏幕截图的例子。不过,Pyppeteer也适用于更复杂的动态网站。在下一节中,您将探索第二个例子,学习如何构建一个简单的网络爬虫脚本,从交互式网站中提取主题标题。这正是Pyppeteer的亮点,因为使用其他工具如request或BeautifulSoup几乎不可能完成这个任务。
使用Pyppeteer抓取复杂页面内容 假设您的任务是从Educative.io/edpresso网站的给定主题名称列表中爬取文章创意。页面内容会根据您在搜索框中输入的内容进行交互式渲染。
通过观看下面的GIF,您可以快速构思脚本需要执行的步骤,以有效提取互动式文章的创意。这些步骤可能包括:
找到搜索框。 在搜索框中输入目标主题。 等待主题加载。 提取关于该主题的所有文章标题。 从搜索框中删除主题。 重复步骤2-5,直到迭代完所有必要的主题。 设置 在实现算法之前,请记住,Pyppeteer默认以无头模式启动Chromium浏览器。对于构建复杂脚本,通常最好手动配置为非无头模式,因为这可以减轻盲目调试的负担。
以下是如何将Pyppeteer配置为非无头模式:
browser = await launch({“headless”: False})
browser = await launch({“headless”: False, “args”: [“–start-maximized”]})
现在我们再来设置一下脚本的各个环节。
1.找到搜索框 打开网站的第一行代码将类似于本文第一个例子中使用的代码。不过在这里,你需要添加一个新的行,用一个CSS选择器来定位搜索框。你的代码将看起来像这样:
import asyncio
from typing import List
from pyppeteer import launch
async def get_article_titles(keywords: List[str]):
# launch browser in headless mode
browser = await launch({“headless”: False, “args”: [“–start-maximized”]})
# create a new page
page = await browser.newPage()
# set page viewport to the largest size
await page.setViewport({“width”: 1600, “height”: 900})
# navigate to the page
await page.goto(“https://www.educative.io/edpresso”)
# locate the search box
entry_box = await page.querySelector(
“#__next > div.ed-grid > div.ed-grid-main > div > div.flex.flex-row.items-center.justify-around.bg-gray-50.dark\:bg-dark.lg\:py-0.lg\:px-6 > div > div.w-full.p-0.m-0.flex.flex-col.lg\:w-1\/2.lg\:py-0.lg\:px-5 > div.pt-6.px-4.pb-0.lg\:sticky.lg\:p-0 > div > div > div.w-full.dark\:bg-dark.h-12.flex-auto.text-sm.font-normal.rounded-sm.cursor-text.inline-flex.items-center.hover\:bg-alphas-black06.dark\:hover\:bg-gray-A900.border.border-solid.overflow-hidden.focus-within\:ring-1.border-gray-400.dark\:border-gray-900.focus-within\:border-primary.dark\:focus-within\:border-primary-light.focus-within\:ring-primary.dark\:focus-within\:ring-primary-light > input”
)
2.撰写目标主题
await entry_box.type(keyword)
3.等待主题加载
await page.waitFor(4000)
4.提取文章的想法
topics = await page.querySelectorAll(“h2”)
for topic in topics:
title = await topic.getProperty(“textContent”)
# print the article titles
print(await title.jsonValue())
5.从搜索框中删除主题
for _ in range(len(keyword)):
await page.keyboard.press(“Backspace”)
6.重复步骤2-5(对主题进行迭代) for keyword in keywords:
# type keyword in search box
await entry_box.type(keyword)
# wait for search results to load
await page.waitFor(4000)
# extract the article titles
topics = await page.querySelectorAll(“h2”)
# print the article titles
for topic in topics:
title = await topic.getProperty(“textContent”)
print(await title.jsonValue())
# clear the input box
for _ in range(len(keyword)):
await page.keyboard.press(“Backspace”)
完成脚本 现在你已经建立了算法的各个部分,现在是时候把整个脚本放在一起了。你的完整源代码应该是这样的:
import asyncio
from typing import List
from pyppeteer import launch
async def get_article_titles(keywords: List[str]):
browser = await launch({“headless”: False, “args”: [“–start-maximized”]})
page = await browser.newPage()
await page.setViewport({“width”: 1600, “height”: 900})
await page.goto(“https://www.educative.io/edpresso”)
entry_box = await page.querySelector(
“#__next > div.ed-grid > div.ed-grid-main > div > div.flex.flex-row.items-center.justify-around.bg-gray-50.dark\:bg-dark.lg\:py-0.lg\:px-6 > div > div.w-full.p-0.m-0.flex.flex-col.lg\:w-1\/2.lg\:py-0.lg\:px-5 > div.pt-6.px-4.pb-0.lg\:sticky.lg\:p-0 > div > div > div.w-full.dark\:bg-dark.h-12.flex-auto.text-sm.font-normal.rounded-sm.cursor-text.inline-flex.items-center.hover\:bg-alphas-black06.dark\:hover\:bg-gray-A900.border.border-solid.overflow-hidden.focus-within\:ring-1.border-gray-400.dark\:border-gray-900.focus-within\:border-primary.dark\:focus-within\:border-primary-light.focus-within\:ring-primary.dark\:focus-within\:ring-primary-light > input”
)
for keyword in keywords:
print(“====================== {} ======================”.format(keyword))
# type keyword in search box
await entry_box.type(keyword)
# wait for search results to load
await page.waitFor(4000)
# extract the article titles
topics = await page.querySelectorAll(“h2”)
for topic in topics:
title = await topic.getProperty(“textContent”)
# print the article titles
print(await title.jsonValue())
# clear the input box
for _ in range(len(keyword)):
await page.keyboard.press(“Backspace”)
print(“Starting…”)
asyncio.get_event_loop().run_until_complete(
get_article_titles([“python”, “opensource”, “opencv”])
)
print(“Finished extracting articles titles”)
运行脚本 一旦你的脚本被编译完成,就可以看看它是否工作了。像你通常运行Python脚本那样启动该脚本,如图所示:
$ python3 app.py
Starting…
====================== python ======================
What is the contextlib module?
What is the difference between String find() and index() method?
Installing pip3 in Ubuntu
What is a private heap space?
……
====================== opensource ======================
Knative
How to use ASP.NET Core
What is apache Hadoop?
What is OpenJDK?
What is Azure Data Studio?
…..
====================== opencv ======================
What is OpenCV in Python?
Eye Blink detection using OpenCV, Python, and Dlib
How to capture a frame from real-time camera video using OpenCV
Finished extracting articles titles
[文中代码源自Scrapingbee]
当你运行你的脚本时,它会自动启动Chromium浏览器,然后为Educative.io页面打开一个新标签。然后,它将通过上面强调的所有步骤,打印出每个关键词的爬取文章标题。如果你在运行你的脚本时看到与上述输出类似的结果,那么恭喜你,你成功了
总结 在本文中,您已了解了网页爬取,并探索了Pyppeteer构建脚本的能力,可以实现从简单的网站屏幕截图捕捉到动态、互动网页的网络爬取。然而,这只是基础知识。现在您已经掌握了这些基本知识,请花些时间去访问Pyppeteer的官方文档,满足您的好奇心,探索更多高级功能和用法。
本文转载自-