参考文章
以下都是基于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
吧
用这个做选择器非常舒爽
代码结构优化
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
, 便于在回调函数中抓取并处理所有的元素