使用微软 Playwright 进行网页浏览器自动化

这是有关使用微软 Playwright 自动化 Web 浏览器的指南。我们将介绍 Playwright 的安装、打开浏览器、以及爬取 Naver 新闻等内容。

4,653
使用微软 Playwright 进行网页浏览器自动化

0. 什么是Playwright?

Playwright是由微软开发的开源库,用于自动化Web浏览器。

虽然最初并非为Web抓取而设计,但通过适当地组合浏览器和设置,它在这个领域表现出色。

可以在Node.js和Python等多种语言中使用,目前支持Chrome、Firefox、WebKit(移动Safari)、Electron等多个浏览器。

本文中将使用Python。


1. 安装Playwright

安装playwright包:

pip install playwright

安装必要的浏览器:

playwright install

2. 打开浏览器

让我们尝试访问Naver首页进行测试。

# 패키지 import
import asyncio # 비동기 라이브러리
from playwright.async_api import Playwright, async_playwright

async def run(playwright: Playwright) -> None:
    # headless=False => 브라우저 GUI 모드로 실행
    browser = await playwright.chromium.launch(headless=False) # 크롬 사용
    context = await browser.new_context()  # 새 콘텍스트 생성
    page = await context.new_page()  # 새 페이지 열기
    await page.goto("<https://naver.com/>")  # 네이버 홈페이지로 이동

    await context.close() # 콘텍스트 종료
    await browser.close() # 브라우저 종료

async def main() -> None:
    async with async_playwright() as playwright:
        await run(playwright)

asyncio.run(main()) # 실행

notion image

上述代码运行结果,浏览器以“隐私模式”打开,并成功访问了Naver首页。


3. 爬取Naver新闻

让我们尝试爬取Naver新闻的搜索结果列表。

3.1. 获取URL

根据URL规则,我们得到以下结果:

f"<https://search.naver.com/search.naver?where=news&query=>{인코딩된 검색어}&sort={정렬 기준}&field=0&pd=3&start={시작 페이지}"
  • 编码后的搜索词: 使用quote_plus方法添加搜索词。

  • 排序选项: {"相关度排序": 0, "最新排序": 1, "最旧排序": 2}

  • 起始页面: {第1页: 1, 第2页: 11},每页增加10。

因此,搜索URL如下:

# 정렬 옵션("관련도순")과 시작 페이지("1")은 고정
search_url = f"<https://search.naver.com/search.naver?where=news&query={quote_plus(keyword)}&sort=0&field=0&pd=3&start=1>"

notion image

访问该URL,您将看到与输入关键字相关的Naver新闻搜索结果。

3.2. 收集数据 + xpath

  • 文章列表: //*[@class='list_news']/li

  • 文章URL: .//a[@class='news_tit']href属性

  • 媒体: .//a[@class='info press']

  • 发布日期: .//div[@class='info_group']/span[@class='info']

  • 标题: .//a[@class='news_tit']title属性

  • 摘要: .//div[@class='news_dsc']

3.3. 爬取方法

3.3.1. 使用xpath选择元素

在playwright中,可以按以下方式使用xpath选择元素:

title_element = await page.query_selector("xpath=//a[@class='news_tit']")

使用await暂停代码执行,直到query_selector方法完成。

将xpath作为参数传递,但在"xpath="后面添加。

3.3.2. 获取文本

HTML元素的文本可以使用inner_text()方法获取。

但在playwright中,由于异步访问Web元素,无法同时选择元素并获取文本。

请使用await等待前面的操作完成。

# HTML 요소 선택
title_element = await page.query_selector("xpath=//a[@class='news_tit']")
# 텍스트 가져오기
title_text = await title_element.inner_text()

3.3.3. 获取属性

notion image

要从类似上述HTML元素中获取属性,请使用get_attribute()函数。

同样,使用await

# HTML 요소 선택
title_element = await page.query_selector("xpath=//a[@class='news_tit']")
# href 속성 가져오기
news_link = await title_element.get_attribute("href")
# title 속성 가져오기
title = await title_element.get_attribute("title")

3.4. 爬取代码

3.4.1. 导入包

import re
import asyncio
from pprint import pprint
from datetime import datetime, timedelta
from urllib.parse import quote_plus
from playwright.async_api import Playwright, async_playwright

3.4.2. 转换发布日期函数

常规情况:

notion image

问题情况:

notion image

当将发布日期xpath设置为.//div[@class='info_group']/span[@class='info']时,由于上述图片中的“16면 TOP”和“4小时前”的class均为'info',会导致错误。

因此,如果时间包含“面”,则返回错误消息,否则添加一个函数将日期格式转换为%Y-%m-%d格式。

async def convert_write_date(raw_date):
    now = datetime.now()

    if "면" in raw_date:
        return f"[error] raw_date is not datetime form: {raw_date}"

    if "분 전" in raw_date:
        minutes = re.findall('\d+', raw_date)[0]
        article_date = now - timedelta(minutes=float(minutes))
    elif "시간 전" in raw_date:
        hours = re.findall('\d+', raw_date)[0]
        article_date = now - timedelta(hours=float(hours))
    elif "일 전" in raw_date:
        days = re.findall('\d+', raw_date)[0]
        article_date = now - timedelta(days=float(days))
    else:
        article_date = datetime.strptime(raw_date, "%Y-%m-%d")

    article_date = datetime.strftime(article_date, "%Y-%m-%d")

    return article_date

3.4.3. run函数

async def run(playwright: Playwright) -> None:
    # 파라미터 설정
    keyword = input("Keyword: ")

    # 컨텍스트 및 브라우저 설정
    browser = await playwright.chromium.launch(headless=False)
    context = await browser.new_context()
    page = await context.new_page()

    # 브라우저 이동
    search_url = f"<https://search.naver.com/search.naver?where=news&query={quote_plus(keyword)}&sort=0&field=0&pd=3&start=1>"
    await page.goto(search_url)

    # 검색 결과 리스트
    articles = await page.query_selector_all("xpath=//*[@class='list_news']/li")

    # 각 리스트에 대해 반복
    for article in articles:
        article_info = {}

        # 기사 URL, 제목
        title_element = await article.query_selector("xpath=.//a[@class='news_tit']")
        article_info["URL"] = await title_element.get_attribute("href")
        article_info["제목"] = await title_element.get_attribute("title")

        # 언론사
        press_element = await article.query_selector("xpath=.//a[@class='info press']")
        raw_press = await press_element.inner_text()
        article_info["언론사"] = raw_press.replace("언론사 선정", "")

        # 작성일자
        date_element = await article.query_selector("xpath=.//div[@class='info_group']/span[@class='info']")
        raw_date = await date_element.inner_text()
        # raw_date에 에러 메시지가 있을 경우 HTML 재선택
        if "[error]" in await convert_write_date(raw_date):
            date_element_list = await article.query_selector_all("xpath=.//div[@class='info_group']/span[@class='info']")
            date_element = date_element_list[-1] # 마지막 요소
            raw_date = await date_element.inner_text()
            if "[error]" in await convert_write_date(raw_date):
                raise # 작성일자 찾지 못해 에러 발생
            article_info["작성일자"] = await convert_write_date(raw_date)
        else:
            article_info["작성일자"] = await convert_write_date(raw_date)

        # 본문 요약
        summary_element = await article.query_selector("xpath=.//div[@class='news_dsc']")
        summary = await summary_element.inner_text()
        article_info["본문 요약"] = summary

        print("=" * 70)
        pprint(article_info)

    # 컨텍스트 및 브라우저 종료
    await context.close()
    await browser.close()

3.4.4. 执行run函数

async def main() -> None:
    async with async_playwright() as playwright:
        await run(playwright)


asyncio.run(main())

3.5. 收集结果

以下是搜索“AI”后的Naver新闻搜索结果:

Keyword: AI
======================================================================
{'URL': '<http://www.newsis.com/view/?id=NISX20230908_0002443154&cID=10406&pID=13100>',
 '본문 요약': '정부가 군 장병과 대학생 등을 대상으로 국방 인공지능(AI) 기술 활용 대회를 진행한다. 청년들의 AI 기술 활용 능력을 '
          "통해 국방 분야 난제 해결에 나선다는 목표다. 과학기술정보통신부와 국방부는 '2023 제2회 국방...",
 '언론사': '뉴시스',
 '작성일자': '2023-09-08',
 '제목': "과기정통부, 국방부와 '국방 AI' 경진대회 개최…총 상금 8200만원"}
======================================================================
{'URL': '<https://www.mk.co.kr/article/10825161>',
 '본문 요약': '마이크로소프트가 인공지능(AI) 기술을 이용해 암 식별 프로그램을 개발한다. MS는 7일(현지시각) 디지털 병리학 '
          '제공업체인 페이지(Paige)와 협력해 세계 최대의 이미지 기반 AI 모델을 구축하고 있다고 밝혔다. 이 AI...',
 '언론사': '매일경제',
 '작성일자': '2023-09-08',
 '제목': '“희소암까지 싹 잡아낸다”…MS, AI 기반 암 식별 프로그램 개발'}
======================================================================
{'URL': '<https://zdnet.co.kr/view/?no=20230907220708>',
 '본문 요약': '초거대 인공지능(AI)을 전산업으로 확산하기 위한 산‧학‧연 전문가 협의체가 만들어졌다. 과기정통부는 이런 목적을 가진 '
          "'AI 데이터 융합 네트워크' 발족식을 8일 서울 롯데백화점 인근 이비스 앰배서더 명동 호텔 19층...",
 '언론사': '지디넷코리아',
 '작성일자': '2023-09-08',
 '제목': '"초거대AI 전산업 확산"···AI데이터 융합 네트워크 발족'}
======================================================================
{'URL': '<https://www.news1.kr/articles/5164994>',
 '본문 요약': '박정환 문화전문기자 = 인공지능(Ai)이 국내 거주 중인 외국인과 다문화 가정 자녀들의 한국어 실력을... 열리는 '
          "'제1회 AI 한국어 말하기 대회'에서다. 제1회 AI 한국어 말하기 대회는 한글과컴퓨터는 자회사...",
 '언론사': '뉴스1',
 '작성일자': '2023-09-08',
 '제목': '예선 심사위원은 AI…외국인·다문화가정 자녀의 한국어 실력 경연대회'}
======================================================================
{'URL': '<https://www.yna.co.kr/view/AKR20230908046351017?input=1195m>',
 '본문 요약': 'AI) 기술로 진화한 플랫폼을 만들겠다는 비전을 제시했다. 카카오모빌은 8일 서울 강남구 그랜드인터컨티넨탈 '
          "서울파르나스에서 올해로 2회째를 맞는 '넥스트 모빌리티'(NEMO) 행사를 열어 '우리의 세상을 이해하는 AI...",
 '언론사': '연합뉴스',
 '작성일자': '2023-09-08',
 '제목': '카카오모빌 "내년 상반기까지 모빌리티 특화 생성AI 엔진 구축"(종합)'}
======================================================================
{'URL': '<https://www.munhwa.com/news/view.html?no=2023090801071607275001>',
 '본문 요약': '■ 카카오모빌리티‘네모2023’ 내년 상반기 생성AI 엔진 구축 이동·물류·배송분야 적용 계획 모임장소 제안서 '
          '택시호출까지 맞춤여행경로 생성서비스 제시 ‘AI랩’서 자율주행로봇 등 전시 카카오모빌리티가 내년...',
 '언론사': '문화일보',
 '작성일자': '2023-09-08',
 '제목': '“모빌리티에 특화된 생성형 AI엔진 구축”'}
======================================================================
{'URL': '<http://www.edaily.co.kr/news/newspath.asp?newsid=01420246635737824>',
 '본문 요약': '프라이빗 뱅커(PB) 1000여 명이 2차전지 다음으로 인공지능(AI)·반도체 테마 상장지수펀드(ETF)를... '
          '‘인공지능(AI)&반도체’가 335명(32%)의 선택을 받아 1위를 했다고 7일 밝혔다. 이어 249명(23%)이 '
          '△‘2차전지&전기차’...',
 '언론사': '이데일리',
 '작성일자': '2023-09-07',
 '제목': '"2차전지 다음은 AI·반도체"…PB 1000명이 주목한 이유'}
======================================================================
{'URL': '<https://www.etoday.co.kr/news/view/2282422>',
 '본문 요약': '인공지능(AI)보이스봇이 안정적으로 정착되면서, 상담사가 보다 섬세한 고객 케어에 집중할 수 있었던 결과라고 설명했다. '
          'KT는 2017년부터 준비를 시작해, 2021년 4월, 365일 24시간 상담이 가능한 AI 보이스봇 ‘지니’...',
 '언론사': '이투데이',
 '작성일자': '2023-09-08',
 '제목': 'KT, 10년 연속 우수 콜센터…AI가 응대하고 사람이 집중케어'}
======================================================================
{'URL': '<http://news.mt.co.kr/mtview.php?no=2023090810400076118>',
 '본문 요약': '월간큐브/나무는 고객의 월별 투자활동을 시각화해 보여주고 해당 월의 시황을 반영한 인공지능(AI) 음악과 함께 제공하는 '
          '서비스다. 투자자들의 즐거운 순간을 포착해 투자에 대한 긍정적인 경험을 강화하기 위해...',
 '언론사': '머니투데이',
 '작성일자': '2023-09-08',
 '제목': '내 투자가 AI 음악으로…NH투자증권, 월간큐브·월간나무 출시'}
======================================================================
{'URL': '<https://www.hankyung.com/article/202309083127i>',
 '본문 요약': '중국에서 인공지능(AI) 백가쟁명(百家爭鳴) 시대가 열렸다. 기존 중국 정보기술(IT) 업계 강호인 바이두... 다만 '
          "공산당의 사상 검열로 인해 중국산 AI가 글로벌 경쟁에서 뒤처질 경우 '그들만의 리그'가 될 수 있다는...",
 '언론사': '한국경제',
 '작성일자': '2023-09-08',
 '제목': '중국 \'AI 백가쟁명\' 시대 열렸다…"100개 넘는 모델이 전쟁"'}

4. 结论

事实上,Playwright并不是用于Web抓取的工具,而是用于Web测试和自动化的框架。

然而,Playwright在Web抓取方面也是一个非常强大的工具。

虽然本文未涉及,但它具有多样且方便的功能。

支持Chromium、Firefox、WebKit等多种浏览器,使得可以进行不受限于浏览器或引擎的Web抓取,特别是对于现代网站具有高度兼容性。

此外,还可以跳过不必要的图像或样式表加载,从而提高抓取性能。

在进行Web抓取时,我们几乎总是使用bs4或selenium。尽管这些都是出色的库,但如果尝试使用Playwright,您可能会感受到更多优势。

也可以阅读这篇文章:

数据收集,现在自动化

无需编码,5分钟即可开始 · 5000多个网站抓取经验

免费开始 →

1 Comment

Add Comment

Your email won't be published and will only be used for reply notifications.

Cabinet IQ 8305 State Hwy 71 #110, Austin, TX 78735, United States 254-275-5536 Bookmarks Guest 06 Jun 23:16

Cabinet IQ 8305 Ѕtate Hwy 71 #110, Austin, TX 78735, United Ꮪtates 254-275-5536 Bookmarks

继续阅读

Get notified of new posts

We'll email you when 해시스크래퍼 기술 블로그 publishes new content.

Your email will only be used for new post notifications.