到目前为止,我们已经拥有了一个可运行的爬虫。但这基本上就是全部了。如果你想使用 Pyppeteer 构建一个更高级的网页爬虫,就必须为 id 添加更多功能。剧透预警:我们将深入探索面向对象编程的世界。但首先,让我们明确我们的目标。我们希望爬虫能够实现什么功能?
- 使用自定义参数初始化浏览器
- 导航并从网页中提取内容
- 向输入框中输入文本
- 提取单个元素的值
- 从多个元素中提取值
3.1. 自定义选项
那么,我们先创建一个新的 `Scraper` 类,稍后再添加其方法:
class Scraper:
def __init__(self, launch_options: dict) -> None:
self.options = launch_options['options']
self.viewPort = launch_options['viewPort'] if 'viewPort' in launch_options else None
pass
我们为 Scraper 使用的唯一参数是一个 `launch_options` 字典。如您所见,它内部包含两个键。其中一个键定义 Pyppeteer 的启动选项。第二个键要么是 `None`,要么是一个包含 `viewPort` 的 `width` 和 `height` 的字典。后者用于此方法。
3.2. 导航至页面
如果你查看之前使用的函数,会发现它既涵盖了导航功能,也包含从特定 URL 提取原始数据的功能。我们只需稍作调整,将其转换为 Scraper 的方法即可:
async def goto(self, url: str) -> None:
self.browser = await launch(options=self.options)
self.page = await self.browser.newPage()
await self.page.setViewport(self.viewPort) if self.viewPort != None else print('[i] Using default viewport')
await self.page.goto(url)
该方法非常简单。首先,它会使用我们之前设定的自定义选项启动一个新浏览器。随后创建一个新页面,如果 `launch_options` 字典中包含 `viewPort`,则设置页面的视口;否则,它会输出一条简单提示。最后但同样重要的是,它将我们带到目标页面。
3.3. 从页面中提取原始数据
同样,该方法位于初始的 `scraper` 函数中。我们只需等待 `page.content()` 加载并返回其值:
async def get_full_content(self) -> str:
content = await self.page.content()
return content
3.4. 向输入框写入文本
若要使用 Pyppeteer 向输入框写入内容,你需要完成两步操作。首先,定位该元素;其次,向其中添加值。幸运的是,Pyppeteer 提供了实现这两项操作的方法:
async def type_value(self, selector: str, value: str) -> None:
element = await self.page.querySelector(selector)
await element.type(value)
3.5. 从页面提取值
请记住,我们需要能够从单个元素中提取值,也能从多个元素中提取值。虽然可以用一个方法同时处理这两种情况,但我通常喜欢将它们分开。因此,目前我将再添加两个方法:
async def extract_one(self, selector) -> str:
element = await self.page.querySelector(selector)
text = await element.getProperty("textContent")
return await text.jsonValue()
这里,我们使用 `querySelector` 方法定位元素。随后获取 `textContent` 并返回其 `jsonValue()`。另一方面,当需要选择多个元素时,我们将使用 `querySelector`:
async def extract_many(self, selector) -> list:
result = []
elements = await self.page.querySelectorAll(selector)
for element in elements:
text = await element.getProperty("textContent")
result.append(await text.jsonValue())
return result
该方法的工作原理与 `extract_one` 类似,唯一的区别在于返回值。这次我们返回的是所选元素内所有文本组成的列表。我想,至此,我们已实现了所有目标。