@@ -0,0 +1,62 @@
|
||||
# 数据爬取脚本
|
||||
|
||||
本目录包含用于从各种数据源爬取经济数据的脚本。
|
||||
|
||||
## 目录结构
|
||||
|
||||
- `sow-inventory-scraper.js` - 爬取能繁母猪数量数据
|
||||
- `template-scraper.js` - 通用爬取脚本模板
|
||||
|
||||
## 依赖
|
||||
|
||||
- axios - 用于发送HTTP请求
|
||||
- cheerio - 用于解析HTML内容
|
||||
- csv-parser - 用于解析CSV格式数据
|
||||
|
||||
## 安装依赖
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
1. **修改脚本配置**:
|
||||
- 打开相应的爬取脚本
|
||||
- 修改数据源URL和数据提取逻辑
|
||||
|
||||
2. **运行爬取脚本**:
|
||||
```bash
|
||||
node scripts/scraper/sow-inventory-scraper.js
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. **数据来源合规性**:确保爬取的数据来源符合相关法律法规
|
||||
2. **爬虫礼仪**:设置合理的请求间隔,避免对目标网站造成压力
|
||||
3. **数据验证**:爬取后对数据进行验证,确保数据准确性
|
||||
4. **错误处理**:脚本包含基本的错误处理,但可能需要根据实际情况进行调整
|
||||
|
||||
## 扩展指南
|
||||
|
||||
1. **添加新的爬取脚本**:
|
||||
- 复制 `template-scraper.js` 模板
|
||||
- 修改数据源URL和数据提取逻辑
|
||||
- 更新数据库存储逻辑
|
||||
|
||||
2. **修改数据提取逻辑**:
|
||||
- 使用Cheerio选择器提取HTML中的数据
|
||||
- 对于CSV数据,使用csv-parser解析
|
||||
- 对于JSON数据,直接处理响应数据
|
||||
|
||||
3. **数据存储**:
|
||||
- 脚本会自动将数据存储到数据库
|
||||
- 会检查数据是否已存在,存在则更新,不存在则创建
|
||||
|
||||
## 示例
|
||||
|
||||
爬取浙江省能繁母猪数量数据:
|
||||
|
||||
```bash
|
||||
node scripts/scraper/sow-inventory-scraper.js
|
||||
```
|
||||
@@ -0,0 +1,95 @@
|
||||
const axios = require('axios');
|
||||
const cheerio = require('cheerio');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { PrismaClient } = require('../../generated/prisma');
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
// 浙江数据开放网站URL(示例,实际需要根据真实网站修改)
|
||||
const ZHEJIANG_OPEN_DATA_URL = 'https://data.zj.gov.cn/';
|
||||
|
||||
// 能繁母猪数量数据爬取函数
|
||||
async function scrapeSowInventory() {
|
||||
try {
|
||||
console.log('开始爬取浙江省能繁母猪数量数据...');
|
||||
|
||||
// 1. 发送HTTP请求获取页面内容
|
||||
const response = await axios.get(ZHEJIANG_OPEN_DATA_URL, {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 解析HTML内容
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
// 3. 提取数据(这里需要根据实际网站结构修改选择器)
|
||||
// 示例:假设数据在表格中
|
||||
const data = [];
|
||||
|
||||
$('table').each((tableIndex, table) => {
|
||||
$(table).find('tr').each((rowIndex, row) => {
|
||||
if (rowIndex > 0) { // 跳过表头
|
||||
const cells = $(row).find('td');
|
||||
if (cells.length >= 2) {
|
||||
const month = $(cells[0]).text().trim();
|
||||
const inventory = parseInt($(cells[1]).text().trim());
|
||||
|
||||
if (month && !isNaN(inventory)) {
|
||||
data.push({
|
||||
month,
|
||||
inventory
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
console.log(`爬取到 ${data.length} 条数据`);
|
||||
|
||||
// 4. 存储数据到数据库
|
||||
for (const item of data) {
|
||||
try {
|
||||
// 检查数据是否已存在
|
||||
const existing = await prisma.econ_SowInventory.findUnique({
|
||||
where: { month: item.month }
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
// 更新现有数据
|
||||
await prisma.econ_SowInventory.update({
|
||||
where: { month: item.month },
|
||||
data: { inventory: item.inventory }
|
||||
});
|
||||
console.log(`更新数据: ${item.month} - ${item.inventory}`);
|
||||
} else {
|
||||
// 创建新数据
|
||||
await prisma.econ_SowInventory.create({
|
||||
data: item
|
||||
});
|
||||
console.log(`新增数据: ${item.month} - ${item.inventory}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`处理数据 ${item.month} 时出错:`, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('数据爬取和存储完成!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('爬取数据时出错:', error.message);
|
||||
} finally {
|
||||
// 关闭Prisma连接
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
// 导出函数
|
||||
module.exports = { scrapeSowInventory };
|
||||
|
||||
// 如果直接运行此文件
|
||||
if (require.main === module) {
|
||||
scrapeSowInventory();
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
const axios = require('axios');
|
||||
const cheerio = require('cheerio');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { PrismaClient } = require('../../generated/prisma');
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
// 数据源URL(需要根据实际情况修改)
|
||||
const DATA_SOURCE_URL = 'https://example.com/data';
|
||||
|
||||
// 通用数据爬取函数
|
||||
async function scrapeData() {
|
||||
try {
|
||||
console.log('开始爬取数据...');
|
||||
|
||||
// 1. 发送HTTP请求获取页面内容
|
||||
const response = await axios.get(DATA_SOURCE_URL, {
|
||||
headers: {
|
||||
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
|
||||
}
|
||||
});
|
||||
|
||||
// 2. 解析HTML内容
|
||||
const $ = cheerio.load(response.data);
|
||||
|
||||
// 3. 提取数据(需要根据实际网站结构修改)
|
||||
const data = [];
|
||||
|
||||
// 示例:从表格中提取数据
|
||||
$('table').each((tableIndex, table) => {
|
||||
$(table).find('tr').each((rowIndex, row) => {
|
||||
if (rowIndex > 0) { // 跳过表头
|
||||
const cells = $(row).find('td');
|
||||
// 根据实际表格结构提取数据
|
||||
// 示例:假设第一列是日期,第二列是数值
|
||||
if (cells.length >= 2) {
|
||||
const date = $(cells[0]).text().trim();
|
||||
const value = parseFloat($(cells[1]).text().trim());
|
||||
|
||||
if (date && !isNaN(value)) {
|
||||
data.push({
|
||||
date,
|
||||
value
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
console.log(`爬取到 ${data.length} 条数据`);
|
||||
|
||||
// 4. 存储数据到数据库(需要根据实际表结构修改)
|
||||
for (const item of data) {
|
||||
try {
|
||||
// 这里需要根据实际表结构修改
|
||||
// 示例:存储到某个表
|
||||
/*
|
||||
const existing = await prisma.someTable.findUnique({
|
||||
where: { date: item.date }
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
// 更新现有数据
|
||||
await prisma.someTable.update({
|
||||
where: { date: item.date },
|
||||
data: { value: item.value }
|
||||
});
|
||||
console.log(`更新数据: ${item.date} - ${item.value}`);
|
||||
} else {
|
||||
// 创建新数据
|
||||
await prisma.someTable.create({
|
||||
data: item
|
||||
});
|
||||
console.log(`新增数据: ${item.date} - ${item.value}`);
|
||||
}
|
||||
*/
|
||||
} catch (error) {
|
||||
console.error(`处理数据时出错:`, error.message);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('数据爬取和存储完成!');
|
||||
|
||||
} catch (error) {
|
||||
console.error('爬取数据时出错:', error.message);
|
||||
} finally {
|
||||
// 关闭Prisma连接
|
||||
await prisma.$disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
// 导出函数
|
||||
module.exports = { scrapeData };
|
||||
|
||||
// 如果直接运行此文件
|
||||
if (require.main === module) {
|
||||
scrapeData();
|
||||
}
|
||||
Reference in New Issue
Block a user