高效的异步自动化爬虫——PlayWright案例
一.本案例简介:
最近在跟着崔大的书学习playwright自动化爬虫库,这是一个支持异步操作的开源第三方库。在本文中,我将利用这个库,结合其他库编写一个自动化爬虫。也可视为学习完这个库之后的学习成果的检验。目标网站: https://spa6.scrape.center/ 。
二.本次爬虫脚本的实现:
1.需要准备的库:
playwright(请按照相关文档正确配置),redis,asyncio,json库。
2.编写思路:
使用playwright连接网站接口,用css选择器提取电影标签(这里只提取第一页的十部电影,如需提取更多,读者可自己扩展程序);跳转到子网页,再用playwright封装的回调函数捕捉到目标数据;最后存储到本地redis数据库。
3.源代码:
import asyncio
from playwright.async_api import async_playwright
from redis import StrictRedis
import json
class SaveData:
'''定义此类方便利用PlayWright封装的回调函数'''
def init(self,movie_id):
self.movie_id = movie_id
self.redis = StrictRedis(host='localhost',port=6379,db=1)
def __savedata(self,json_data):
self.redis.set(self.movie_id,json_data)
print(f'电影{self.movie_id}数据保存完毕!')
async def callback(self,response):
# 筛选出带有json目标数据的url的response
if 'api/movie' in response.url and response.status == 200:
json_data = json.dumps(await response.json())
self.__savedata(json_data)
async def one_movie_handle(page, url,movie_id):
# 实例化SaveData类
savedata = SaveData(movie_id)
# 开启事件监听
page.on('response',savedata.callback)
# 进入子页面
await page.goto(url)
# 等待子页面加载完毕
await page.wait_for_load_state('networkidle')
# 关闭子页面
await page.close()
async def main():
# 使用chromium作为浏览器驱动
playwright = await async_playwright().start()
browser = await playwright.chromium.launch()
# 新建上下文
context = await browser.new_context()
# 新建选项卡
page_1 = await context.new_page()
# 接入目标网站
await page_1.goto('https://spa6.scrape.center/')
# 等待网页加载完毕
await page_1.wait_for_load_state('networkidle')
# 使用css选择器定位到目标(抓取第一页十部电影)
elements = await page_1.query_selector_all('div.el-card.item.m-t.is-hover-shadow')
# 封装异步任务
tasks = []
for element in elements:
# 获得子页面网址
tag_a = await element.query_selector('a')
url = 'https://spa6.scrape.center' + await tag_a.get_attribute('href')
# 获得电影名称
tag_h2 = await element.query_selector('a > h2')
movie_id = await tag_h2.text_content()
# 新建子页面选项卡
page_2 = await context.new_page()
tasks.append(asyncio.create_task(one_movie_handle(page_2, url,movie_id)))
await asyncio.wait(tasks)
# 关闭浏览器驱动
await browser.close()
if name == '__main__':
asyncio.get_event_loop().run_until_complete(main())
4.补充:
在这个程序中,我定义了一个类,这个类的作用是利用上回调函数提取数据。
四.成果展示:
原文链接:https://blog.csdn.net/m0_63054161/article/details/127557848