You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
4.1 KiB
105 lines
4.1 KiB
import org.jsoup.nodes.Document;
|
|
import org.jsoup.nodes.Element;
|
|
import org.jsoup.select.Elements;
|
|
|
|
import java.io.BufferedWriter;
|
|
import java.io.IOException;
|
|
|
|
/**
|
|
* 中国非物质文化遗产爬虫
|
|
* 爬取 Wikipedia 上的国家级非遗项目列表(1557项)
|
|
* 继承自 BaseCrawler,实现具体的解析逻辑
|
|
*/
|
|
public class IntangibleHeritageCrawler extends BaseCrawler {
|
|
|
|
// Wikipedia 非遗列表页面
|
|
private static final String WIKIPEDIA_URL = "https://zh.wikipedia.org/wiki/国家级非物质文化遗产代表性项目名录";
|
|
// 输出文件路径
|
|
private static final String OUTPUT_FILE = "intangible_heritage.csv";
|
|
// 目标项目数量
|
|
private static final int TARGET_COUNT = 1557;
|
|
|
|
public static void main(String[] args) {
|
|
// 使用多态:父类引用指向子类对象
|
|
BaseCrawler crawler = new IntangibleHeritageCrawler();
|
|
// 调用父类的通用 run 方法,内部会自动执行子类的 parseData 实现
|
|
crawler.run(WIKIPEDIA_URL, OUTPUT_FILE, TARGET_COUNT);
|
|
}
|
|
|
|
/**
|
|
* 重写父类的抽象方法 parseData
|
|
* 实现维基百科非遗表格的解析逻辑
|
|
*/
|
|
@Override
|
|
protected void parseData(Document doc, BufferedWriter writer) throws IOException, InterruptedException {
|
|
// Wikipedia 的表格通常有特定的class
|
|
Elements tables = doc.select("table.wikitable, table.sortable");
|
|
System.out.println("找到 " + tables.size() + " 个表格\n");
|
|
|
|
// 遍历所有表格
|
|
for (Element table : tables) {
|
|
// 提取表格标题(类别)
|
|
String category = "";
|
|
Element caption = table.selectFirst("caption");
|
|
if (caption != null) {
|
|
category = caption.text().trim();
|
|
}
|
|
|
|
// 提取表格行
|
|
Elements rows = table.select("tr");
|
|
System.out.println("表格:" + category + " - 共 " + rows.size() + " 行");
|
|
|
|
int tableCount = 0;
|
|
for (Element row : rows) {
|
|
try {
|
|
// 提取单元格
|
|
Elements cells = row.select("td");
|
|
|
|
if (cells.size() >= 2) {
|
|
// 第一列通常是项目名称
|
|
String name = cells.get(0).text().trim();
|
|
|
|
// 第二列通常是地区
|
|
String region = cells.get(1).text().trim();
|
|
|
|
// 如果有第三列,可能是简介或批次
|
|
String description = "";
|
|
if (cells.size() >= 3) {
|
|
description = cells.get(2).text().trim();
|
|
}
|
|
|
|
// 清理数据(使用父类提供的方法)
|
|
name = cleanCsvField(name);
|
|
category = cleanCsvField(category);
|
|
region = cleanCsvField(region);
|
|
description = cleanCsvField(description);
|
|
|
|
// 如果项目名称不为空且不是表头,则写入CSV
|
|
if (!name.isEmpty() &&
|
|
!name.equals("项目名称") &&
|
|
!name.equals("名称") &&
|
|
!name.equals("序号") &&
|
|
name.length() > 1) {
|
|
|
|
writer.write(String.format("%s,%s,%s,%s", name, category, region, description));
|
|
writer.newLine();
|
|
tableCount++;
|
|
totalCount++;
|
|
|
|
// 打印进度(使用父类提供的方法)
|
|
printProgress(totalCount);
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
System.err.println(" 解析行时出错:" + e.getMessage());
|
|
}
|
|
}
|
|
|
|
System.out.println(" 该表格爬取完成!共 " + tableCount + " 个项目\n");
|
|
|
|
// 延时,避免请求过快(使用父类提供的方法)
|
|
delay();
|
|
}
|
|
}
|
|
}
|
|
|
|
|