欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 爬取动态数据,爬取持久化数据

爬取动态数据,爬取持久化数据

2025/3/12 21:05:02 来源:https://blog.csdn.net/weixin_46281518/article/details/145793972  浏览:    关键词:爬取动态数据,爬取持久化数据

1. 动态内容与静态内容的区别

动态内容通常指通过 JavaScript 渲染或异步加载的数据。静态内容则是页面加载时直接可见的内容,通常通过 HTML 直接获取。很多现代网站都使用 JavaScript 动态渲染页面内容(例如 AJAX 请求)。

头条网站的热榜内容是动态加载的,页面最初只展示一个固定的热榜,而点击“换一换”按钮后,新的热榜内容会通过 JavaScript 异步加载。爬虫需要等待页面加载或等待某个元素(例如热榜内容)出现,才能获取这些数据。

2. 实现步骤

我们将按照以下步骤完成爬取任务:

  • • 打开今日头条网站并定位到热榜区域。

  • • 等待并抓取初始热榜内容。

  • • 点击“换一换”按钮,刷新热榜内容。

  • • 等待新内容加载并输出新的热榜数据。

3. 代码实现

3.1 步骤 1:创建 Playwright 脚本

首先,确保你已安装 Playwright

npm install playwright

然后,创建一个 crawler.js 文件,并将以下代码添加到该文件中:

const { chromium } = require('playwright');(async () => {const browser = await chromium.launch({ headless: true });  // 启动浏览器const page = await browser.newPage();  // 新建一个页面// 打开今日头条网站await page.goto('https://toutiao.com');  // 等待热榜区域加载完成await page.waitForSelector('.home-hotboard');  // 热榜区域的容器(CSS 选择器)// 获取初始的热榜内容let hotList = await page.$$eval('.home-hotboard .news-title', items =>items.map(item => item.textContent.trim())  // 获取每个热榜项的文本内容);console.log('初始热榜内容:');console.log(hotList);// 点击“换一换”按钮const changeButton = await page.$('.refresh');  // 找到“换一换”按钮if (changeButton) {await changeButton.click();  // 点击按钮刷新热榜}// 等待新的热榜内容加载完成await page.waitForSelector('.home-hotboard');  // 等待热榜区域重新加载// 获取刷新后的热榜内容hotList = await page.$$eval('.home-hotboard .news-title', items =>items.map(item => item.textContent.trim())  // 获取新热榜项的文本内容);console.log('刷新后的热榜内容:');console.log(hotList);await browser.close();  // 关闭浏览器
})();

3.2 步骤 2:代码解析

启动浏览器和打开页面

const browser = await chromium.launch({ headless: true });  // 启动浏览器
const page = await browser.newPage();  // 新建一个页面
await page.goto('https://toutiao.com');  // 打开今日头条网站

这里我们启动了一个无头模式的 Chromium 浏览器并访问了头条网站。

等待热榜加载完成

await page.waitForSelector('.home-hotboard');  // 等待热榜区域加载完成

我们使用 waitForSelector 等待页面中的 热榜 区域(通过 CSS 选择器 .home-hotboard)加载完成。

获取初始热榜内容

  hotList = await page.$$eval('.home-hotboard .news-title', items =>items.map(item => item.textContent.trim())  // 获取每个热榜项的文本内容
);
console.log('初始热榜内容:');
console.log(hotList);

使用 $$eval 方法,我们选择了热榜区域内的所有 .news-title 元素,并输出它们的文本内容(即热榜的标题)。

点击“换一换”按钮并等待新内容加载

const changeButton = await page.$('.refresh');  // 找到“换一换”按钮
if (changeButton) {await changeButton.click();  // 点击按钮刷新热榜
}await page.waitForSelector('.home-hotboard');  // 等待热榜区域重新加载

获取刷新后的热榜内容

  hotList = await page.$$eval('.home-hotboard .news-title', items =>items.map(item => item.textContent.trim())  // 获取新热榜项的文本内容
);
console.log('刷新后的热榜内容:');
console.log(hotList);

再次使用 $$eval 方法获取刷新后的热榜项内容,并将其输出到控制台。

关闭浏览器

await browser.close();  // 关闭浏览器

3.3 步骤 3:代码运行

在终端中运行以下命令来执行脚本:

node crawler.js

运行后,脚本会打印出 初始热榜内容 和 刷新后的热榜内容。

梳理

通过本教程,你学会了如何使用 Playwright 爬取动态加载的内容。在实际项目中,很多网站的数据都依赖于 JavaScript 动态渲染和异步加载,掌握如何处理这些动态内容,对于编写有效的爬虫非常重要。

4. 数据存储的需求

在爬取数据后,通常会有以下几种存储方式:

  • • JSON 格式:适合存储结构化的数据,并且便于与其他系统交换。

  • • CSV 格式:适用于存储表格数据,常用于数据分析和处理。

  • • SQLite 数据库:适用于需要长期存储、查询的数据,适合小型的本地数据库需求。
    我们将依次展示如何将爬取的数据保存为 JSONCSV 文件,并将其插入 SQLite 数据库中。

5. 完整代码实现

5.1 环境准备

首先,我们从 头条热榜 爬取数据,并将其分别保存为 JSONCSV 和 SQLite。首先确保你已经安装了 Playwright

npm install playwright

并且安装了 json2csv 的 Node.js 库:

npm install json2csv

并且安装了 SQLite 的 Node.js 库:

npm install sqlite3

还可以通过以下命令确认是否正确按照

npm list json2csv

5.2 完整代码

const { chromium } = require('playwright');
const fs = require('fs');
const { Parser } = require('json2csv');
const sqlite3 = require('sqlite3').verbose();// 设置最大循环次数,避免无限点击
const MAX_CLICKS = 5;(async () => {const browser = await chromium.launch({ headless: false });  // 启动浏览器const page = await browser.newPage();  // 新建一个页面// 打开今日头条网站await page.goto('https://toutiao.com');  // 等待热榜区域加载完成await page.waitForSelector('.home-hotboard');  // 热榜区域的容器(CSS 选择器)// 用来记录已经爬取的热榜内容,避免重复let allHotList = new Set();// 点击“换一换”按钮并获取新的热榜内容for (let i = 0; i < MAX_CLICKS; i++) {// 获取热榜内容let hotList = await page.$$eval('.home-hotboard .news-title', items =>items.map(item => item.textContent.trim())  // 获取每个热榜项的文本内容);console.log(`第 ${i + 1} 次刷新后的热榜内容:`);console.log(hotList);// 去重:将本次内容添加到 Set 中,自动去重hotList.forEach(item => allHotList.add(item));// 点击“换一换”按钮const changeButton = await page.$('.refresh');  // 找到“换一换”按钮if (changeButton) {await changeButton.click();  // 点击按钮刷新热榜}// 等待新的热榜内容加载完成await page.waitForSelector('.home-hotboard');  // 等待热榜区域重新加载}// 将去重后的热榜内容转为数组allHotList = Array.from(allHotList);// 保存到 JSON 文件saveToJson(allHotList);// 保存到 CSV 文件saveToCsv(allHotList);// 保存到 SQLite 数据库saveToSQLite(allHotList);await browser.close();  // 关闭浏览器})();// 保存为 JSON 文件
function saveToJson(data) {const filePath = './hotlist.json';fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8');console.log(`数据已保存到 ${filePath}`);
}// 保存为 CSV 文件
function saveToCsv(data) {if (data.length === 0) {console.log('数据为空,无法保存为 CSV 文件');return;}const filePath = './hotlist.csv';// 定义 CSV 文件的字段(列名)const fields = ['title'];  // 这里只需要定义一个字段名称,假设每个项是字符串const csvParser = new Parser({ fields });// 转换数据为 CSV 格式const csv = csvParser.parse(data.map(item => ({ title: item })));  // 将数据转换为对象数组// 保存为 CSV 文件fs.writeFileSync(filePath, csv, 'utf-8');console.log(`数据已保存到 ${filePath}`);
}// 保存到 SQLite 数据库
function saveToSQLite(data) {const db = new sqlite3.Database('./hotlist.db', sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE, (err) => {if (err) {console.error('数据库打开失败', err);} else {console.log('数据库打开成功');}});// 创建热榜表(如果不存在的话)db.run(`CREATE TABLE IF NOT EXISTS hotlist (id INTEGER PRIMARY KEY AUTOINCREMENT,title TEXT UNIQUE,timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)`, (err) => {if (err) {console.error('创建表失败', err);} else {console.log('热榜表已创建或已存在');}});// 插入数据,确保不重复const stmt = db.prepare('INSERT OR IGNORE INTO hotlist (title, timestamp) VALUES (?, ?)');const currentTimestamp = new Date().toISOString(); // 获取当前时间戳,ISO 格式data.forEach((item) => {stmt.run(item, currentTimestamp, (err) => {if (err) {console.error('插入数据失败', err);} else {console.log('插入数据成功', item);}});});stmt.finalize();  // 完成插入操作// 查询并打印保存的内容db.all('SELECT * FROM hotlist', (err, rows) => {if (err) {console.error('查询出错:', err);} else {console.log('从数据库查询到的热榜数据:');rows.forEach(row => {console.log(`${row.id}: ${row.title} (时间: ${row.timestamp})`);});}});// 关闭数据库连接db.close((err) => {if (err) {console.error('关闭数据库失败', err);} else {console.log('数据库连接已关闭');}});
}

5.3 代码解析

爬取头条热榜内容

以上代码使用了之前Playwright爬取页面上的热榜内容方法。先等待热榜区域加载完成,然后通过 $eval 获取每个热榜项的文本内容。

保存数据为json文件

我们创建了一个名为 saveToJson 的函数,将爬取的热榜数据保存为 JSON格式。我们使用 Node.js 的 fs.writeFileSync 方法将数据写入 hotlist.json 文件。

保存数据为csv文件

我们创建了 saveToCsv 函数,将热榜数据保存为 CSV 格式。使用了 json2csv 库,将数据转换为 CSV 格式并保存为 hotlist.csv 文件。

保存数据到SQLite数据库

我们创建了 saveToSQLite 函数,将爬取的热榜数据保存到 SQLite 数据库。我们首先使用 sqlite3 库创建数据库文件(如果不存在则创建),然后创建一个名为 hotlist 的表,并将热榜内容插入到该表中。最后,我们查询并打印了数据库中存储的内容。

5.4 代码运行

图片

保存输出内容如下

图片

总结

这篇教程,我们学会了如何将爬取的数据保存到 JSONCSV 和 SQLite 数据库中。对于爬虫项目来说,数据存储是一个非常重要的环节,而 SQLite 提供了一个轻量级的本地数据库,非常适合小型项目的数据持久化需求。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词