参考文章

以下都是基于Python的. playwright也支持js和java
强大易用!新一代爬虫利器 Playwright 的介绍
playwright 爬虫使用, 这篇参考了上一篇, 算是学习笔记, 另外增加了cookie使用
Scraping the web with Playwright
官方文档

概述

Playwright用作爬虫入门最麻烦的就是, 一开始看官方介绍文档最费劲没用. 官方文档上来就是介绍怎么测试, 运行用的命令也不一样, 其实完全不需要那么麻烦.

安装

npm i playwright

正常的安装方式. 如果是官方文档 ,这一步就麻烦很多.

使用

官方文档上来就导入了test库, 而用于爬虫完全不需要. 以爬取eastmoney的新闻为例:

const playwright = require('playwright');
async function main() {
    const browser = await playwright.chromium.launch({
        headless: false // setting this to true will not run the UI
    });

    const page = await browser.newPage();
    await page.goto('https://so.eastmoney.com/news/s?keyword=%E5%90%9B%E5%AE%9E%E7%94%9F%E7%89%A9');
    const titles = await page.$$eval('.news_item', ele=>{
      // return ele.innerText
      let t = []
      for(e of ele){
        t.push({
          title: e.querySelector('.news_item_t a').text,
          link: e.querySelector('.news_item_t a').href,
          time: e.querySelector('.news_item_time').textContent,
        })
      }
      return t
    })
    console.log(titles)
    await page.waitForTimeout(5000); // wait for 5 seconds
    await browser.close();
}

main();

正式进入爬虫前有三步: 1. playwright打开浏览器; 2. 浏览器打开空页面; 3. 空页面打开网址;
正式爬虫就是用page.$eval或者page.$$eval函数从页面的上下文环境(等同于浏览器的console)中运行js并返回.
$eval相当于浏览器console中的$, 而$==document.querySelector, 必填参数第一个是选择器, 第二个是回调函数element=>{}, element是第一个选择到的元素
$$eval相当于浏览器console中的$$, 而$$==document.querySelectorAll, , 必填参数第一个是选择器, 第二个是回调函数elements=>{}, elements是选择到的所有元素数组.
然后在console环境整理好所有内容, return出来就好了.
这一步真的so easy, 比scrapy+splash+scrapy_splash不要强太多.

但值得注意的一点是, 很多网站上都是用了jquery导致$被jquery占用后无法正常选择,这时候还是老老实实用回document.querySelector

神器 selectorgadget

用这个做选择器非常舒爽

代码结构优化

const playwright = require('playwright');

async function main() {
  const browser = await playwright.chromium.launch({
      headless: false // setting this to true will not run the UI
  });

  const page = await browser.newPage();
  await page.goto('https://so.eastmoney.com/news/s?keyword=%E5%90%9B%E5%AE%9E%E7%94%9F%E7%89%A9');
  await scraper(page)
  await scraper(page)

  await page.waitForTimeout(5000); // wait for 5 seconds
  await browser.close();
}

async function scraper(page){
  let titles = await page.$eval('body', scraperCb)
  console.log(titles)
  await page.waitForTimeout(500); // wait for 5 seconds
}

function scraperCb(body){
  let t = []

  function getTitles(){
    let ele = body.querySelectorAll('.news_item')
    for(e of ele){
      t.push({
        title: e.querySelector('.news_item_t a').text,
        link: e.querySelector('.news_item_t a').href,
        time: e.querySelector('.news_item_time').textContent,
      })
    }
  }

  getTitles()
  body.querySelector('.fydot~ a+ a').click()

  return t
}

main();

改成三个函数的结构:

  • main函数: 负责进入页面, 循环运行爬虫抓取下一页
  • scraper函数: 负责运行$eval函数, 获取页面返回值, 并点击下一页, 等待执行完毕.
  • scraperCb函数: 为$eval回调的函数, 内容在页面上下文运行, 其中的变量与爬虫主程序完全隔离.
    另外, scraper函数选择器改为body, 便于在回调函数中抓取并处理所有的元素

标签: none 阅读量: 2377

添加新评论