Skip to content

Commit 78d6b9c

Browse files
authored
Merge pull request opendatalab#38 from e06084/main
feat: add dataset statics script
2 parents 480b889 + 219c681 commit 78d6b9c

File tree

6 files changed

+1750
-17
lines changed

6 files changed

+1750
-17
lines changed

README.md

Lines changed: 112 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,23 +74,30 @@ print(f"Overall Score: {result.overall_metrics['overall']:.4f}")
7474
{
7575
"track_id": "0b7f2636-d35f-40bf-9b7f-94be4bcbb396",
7676
"html": "<html><body><h1 cc-select=\"true\">这是标题</h1></body></html>", # 人工标注带cc-select="true" 属性
77-
"groundtruth_content": "# 标题\n\n正文内容",
78-
"groundtruth_content_list": [
79-
{"type": "heading", "content": "标题", "level": 1},
80-
{"type": "paragraph", "content": "正文内容"}
81-
],
8277
"url": "https://orderyourbooks.com/product-category/college-books-p-u/?products-per-page=all",
83-
"layout_id": "orderyourbooks.com_4",
84-
"max_layer_n": 10,
85-
"url_host_name": "orderyourbooks.com",
86-
"raw_warc_path": "s3://cc-raw-huawei/crawl-data/CC-MAIN-2025-13/segments/1742004433093.21/warc/CC-MAIN-20250319080618-20250319110618-00909.warc.gz?bytes=461610805,172252",
87-
"language": "en",
88-
"__dom_depth": 19,
89-
"__dom_width": 10231,
90-
"__type": "__max_depth",
91-
"__tag": "DOM_WIDTH",
92-
"marked_type": "unwanted", # normal:正常标注的网页;unable:正文内容无法抉择;unwanted:无需标注的网页;
93-
"unwanted_reason": "list"
78+
"main_html": "<h1 cc-select=\"true\">这是标题</h1>", # 从html中剪枝得到的正文html
79+
"convert_main_content": "# 这是标题", # 从main_html+html2text转化来
80+
"groundtruth_content": "# 这是标题", # 人工校准的markdown(部分提供)
81+
"meta": {
82+
"language": "en", # 网页的语言
83+
"style": "artical", # 网页的文体
84+
"DOM_WIDTH": 176,
85+
"DOM_DEPTH": 27,
86+
"text_linktext_ratio": 0.12252270850536746,
87+
"table_text_ratio": 0,
88+
"table_dom_depth": -1,
89+
"text_distribution_dispersion": 0.2663,
90+
"table": [], # [], ["layout"], ["data"], ["layout", "data"]
91+
"equation": [], # [], ["inline"], ["interline"], ["inline", "interline"]
92+
"code": [], # [], ["inline"], ["interline"], ["inline", "interline"]
93+
"table_complexity_score": 0,
94+
"dom_complexity_score": 0.8442,
95+
"text_dispersion_score": 0.2663,
96+
"content_diversity_score": 0,
97+
"link_complexity_score": 0.1225,
98+
"overall_complexity_score": 0.3083,
99+
"level": "mid" # simple, mid, hard
100+
}
94101
}
95102
```
96103

@@ -197,6 +204,95 @@ class MyExtractor(BaseExtractor):
197204
ExtractorFactory.register("my-extractor", MyExtractor)
198205
```
199206

207+
### 数据集统计分析工具
208+
209+
WebMainBench 提供了强大的数据集统计分析工具 `scripts/statics.py`,用于分析数据集的各种特征并自动生成复杂度评分和难易程度分类。
210+
211+
#### 功能特性
212+
213+
- **DOM结构分析**:计算网页DOM树的深度和宽度
214+
- **文本链接比例分析**:统计文本与链接的比例关系
215+
- **表格复杂度分析**:评估表格内容的复杂程度
216+
- **内容类型检测**:自动识别公式、代码、表格等特殊内容
217+
- **复杂度评分**:基于多维度指标计算综合复杂度得分
218+
- **动态难易程度分类**:基于数据分布自动分类为 simple/mid/hard
219+
220+
#### 使用方法
221+
222+
```bash
223+
# 基本用法
224+
python scripts/statics.py data/input.jsonl --output data/output_with_stats.jsonl
225+
226+
# 使用默认数据集
227+
python scripts/statics.py
228+
```
229+
230+
#### 参数说明
231+
232+
```bash
233+
# 查看所有可用参数
234+
python scripts/statics.py --help
235+
236+
```
237+
238+
#### 输出结果
239+
240+
工具会在每条数据的 `meta` 字段中添加以下统计信息:
241+
242+
```json
243+
{
244+
"meta": {
245+
"DOM_DEPTH": 25, // DOM树深度
246+
"DOM_WIDTH": 1200, // DOM树宽度
247+
"text_linktext_ratio": 0.85, // 文本链接比例
248+
"table_complexity_score": 0.3, // 表格复杂度得分
249+
"dom_complexity_score": 0.6, // DOM复杂度得分
250+
"text_dispersion_score": 0.4, // 文本分布得分
251+
"content_diversity_score": 0.7, // 内容多样性得分
252+
"link_complexity_score": 0.5, // 链接复杂度得分
253+
"overall_complexity_score": 0.52, // 综合复杂度得分
254+
"level": "mid" // 难易程度 (simple/mid/hard)
255+
}
256+
}
257+
```
258+
259+
#### 复杂度评分算法
260+
261+
综合复杂度得分由以下维度加权计算:
262+
263+
- **DOM结构复杂度 (25%)**:基于DOM深度和宽度,使用动态归一化
264+
- **文本分布复杂度 (25%)**:基于文本在DOM中的分布离散程度
265+
- **内容多样性 (25%)**:基于公式、代码、表格等特殊内容的种类
266+
- **链接复杂度 (25%)**:基于文本与链接的比例关系
267+
268+
#### 运行示例
269+
270+
```bash
271+
# 分析数据集并生成统计报告
272+
python scripts/statics.py data/sample_dataset.jsonl --output data/analyzed_dataset.jsonl
273+
274+
# 输出示例:
275+
🔄 第一阶段: 计算基础统计和复杂度得分...
276+
📊 已处理 100 条数据...
277+
📊 已处理 200 条数据...
278+
279+
🔄 第二阶段: 计算动态阈值和难易程度分类...
280+
📊 复杂度分布阈值计算:
281+
总样本数: 1,827
282+
30%分位数 (simple/mid分界): 0.3245
283+
70%分位数 (mid/hard分界): 0.6789
284+
复杂度得分范围: 0.0944 - 1.0000
285+
286+
📊 难易程度分类结果:
287+
Simple: 548 (30.0%)
288+
Mid: 731 (40.0%)
289+
Hard: 548 (30.0%)
290+
291+
📝 正在写入数据到: data/analyzed_dataset.jsonl
292+
✅ 成功写入 1,827 条数据
293+
```
294+
295+
200296
## 项目架构
201297

202298
```

examples/basic_usage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -889,7 +889,7 @@ def demo_llm_webkit_with_preprocessed_html_evaluation():
889889

890890
# 1. 从真实数据集加载包含预处理HTML的数据
891891
print("1. 从真实数据集加载预处理HTML数据...")
892-
dataset_path = Path("data/WebMainBench_1827_v1_WebMainBench_dataset_merge_with_llm_webkit.jsonl")
892+
dataset_path = Path("data/track_id_diff_result_56.jsonl")
893893
print(f"📂 数据集文件: {dataset_path}")
894894

895895
# 加载数据集

scripts/diff_jsonl.py

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
#!/usr/bin/env python3
2+
"""
3+
比较两个JSONL文件,找出track_id在文件1中存在但在文件2中不存在的数据
4+
"""
5+
import json
6+
import sys
7+
from pathlib import Path
8+
9+
def load_track_ids(jsonl_file):
10+
"""
11+
从JSONL文件中加载所有track_id
12+
13+
Args:
14+
jsonl_file: JSONL文件路径
15+
16+
Returns:
17+
set: track_id集合
18+
"""
19+
track_ids = set()
20+
file_path = Path(jsonl_file)
21+
22+
if not file_path.exists():
23+
print(f"❌ 文件不存在: {file_path}")
24+
return track_ids
25+
26+
print(f"📖 正在读取文件: {file_path.name}")
27+
28+
line_count = 0
29+
try:
30+
with open(file_path, 'r', encoding='utf-8') as f:
31+
for line_num, line in enumerate(f, 1):
32+
line = line.strip()
33+
if not line:
34+
continue
35+
36+
line_count += 1
37+
38+
# 每处理1000行显示进度
39+
if line_count % 1000 == 0:
40+
print(f" 📊 已处理 {line_count} 行...")
41+
42+
try:
43+
data = json.loads(line)
44+
track_id = data.get('track_id')
45+
46+
if track_id:
47+
track_ids.add(track_id)
48+
49+
except json.JSONDecodeError as e:
50+
print(f" ⚠️ 第 {line_num} 行JSON解析错误: {e}")
51+
continue
52+
53+
except Exception as e:
54+
print(f"❌ 读取文件时出错: {e}")
55+
return set()
56+
57+
print(f" ✅ 共找到 {len(track_ids)} 个唯一track_id")
58+
return track_ids
59+
60+
def load_data_with_track_ids(jsonl_file, target_track_ids):
61+
"""
62+
从JSONL文件中加载指定track_id的数据
63+
64+
Args:
65+
jsonl_file: JSONL文件路径
66+
target_track_ids: 目标track_id集合
67+
68+
Returns:
69+
list: 匹配的数据列表
70+
"""
71+
matched_data = []
72+
file_path = Path(jsonl_file)
73+
74+
if not file_path.exists():
75+
print(f"❌ 文件不存在: {file_path}")
76+
return matched_data
77+
78+
print(f"📖 正在从 {file_path.name} 中提取目标数据...")
79+
80+
line_count = 0
81+
found_count = 0
82+
83+
try:
84+
with open(file_path, 'r', encoding='utf-8') as f:
85+
for line_num, line in enumerate(f, 1):
86+
line = line.strip()
87+
if not line:
88+
continue
89+
90+
line_count += 1
91+
92+
# 每处理1000行显示进度
93+
if line_count % 1000 == 0:
94+
print(f" 📊 已处理 {line_count} 行,找到 {found_count} 条目标数据...")
95+
96+
try:
97+
data = json.loads(line)
98+
track_id = data.get('track_id')
99+
100+
if track_id in target_track_ids:
101+
matched_data.append(data)
102+
found_count += 1
103+
104+
except json.JSONDecodeError as e:
105+
print(f" ⚠️ 第 {line_num} 行JSON解析错误: {e}")
106+
continue
107+
108+
except Exception as e:
109+
print(f"❌ 读取文件时出错: {e}")
110+
return []
111+
112+
print(f" ✅ 共找到 {len(matched_data)} 条目标数据")
113+
return matched_data
114+
115+
def main():
116+
"""主函数"""
117+
# 默认输入文件
118+
file1_default = "data/filtered_normal_data_1883.jsonl"
119+
file2_default = "data/WebMainBench_1827_v1_WebMainBench_dataset_merge_with_llm_webkit.jsonl"
120+
121+
# 检查命令行参数
122+
if len(sys.argv) >= 3:
123+
file1 = sys.argv[1]
124+
file2 = sys.argv[2]
125+
else:
126+
file1 = file1_default
127+
file2 = file2_default
128+
129+
print("=" * 80)
130+
print("🔍 比较JSONL文件中的track_id差异")
131+
print("=" * 80)
132+
print(f"📁 文件1 (源文件): {file1}")
133+
print(f"📁 文件2 (对比文件): {file2}")
134+
print(f"🎯 目标: 找出在文件1中存在但在文件2中不存在的track_id数据")
135+
print()
136+
137+
# 步骤1: 加载文件1的所有track_id
138+
print("🔸 步骤1: 加载文件1的track_id...")
139+
track_ids_file1 = load_track_ids(file1)
140+
141+
if not track_ids_file1:
142+
print("❌ 文件1中没有找到有效的track_id")
143+
return
144+
145+
print()
146+
147+
# 步骤2: 加载文件2的所有track_id
148+
print("🔸 步骤2: 加载文件2的track_id...")
149+
track_ids_file2 = load_track_ids(file2)
150+
151+
if not track_ids_file2:
152+
print("❌ 文件2中没有找到有效的track_id")
153+
return
154+
155+
print()
156+
157+
# 步骤3: 计算差集
158+
print("🔸 步骤3: 计算差集...")
159+
diff_track_ids = track_ids_file1 - track_ids_file2
160+
common_track_ids = track_ids_file1 & track_ids_file2
161+
162+
print(f" 📊 文件1中的track_id数量: {len(track_ids_file1):,}")
163+
print(f" 📊 文件2中的track_id数量: {len(track_ids_file2):,}")
164+
print(f" 📊 共同的track_id数量: {len(common_track_ids):,}")
165+
print(f" ⭐ 差异的track_id数量: {len(diff_track_ids):,}")
166+
167+
if not diff_track_ids:
168+
print("\n🎉 没有发现差异!文件1中的所有track_id在文件2中都存在。")
169+
return
170+
171+
print()
172+
173+
# 步骤4: 提取差异数据
174+
print("🔸 步骤4: 提取差异数据...")
175+
diff_data = load_data_with_track_ids(file1, diff_track_ids)
176+
177+
if not diff_data:
178+
print("❌ 没有找到差异数据")
179+
return
180+
181+
print()
182+
183+
# 步骤5: 保存结果
184+
print("🔸 步骤5: 保存差异数据...")
185+
output_file = "data/track_id_diff_result.jsonl"
186+
187+
try:
188+
with open(output_file, 'w', encoding='utf-8') as f:
189+
for data in diff_data:
190+
f.write(json.dumps(data, ensure_ascii=False) + '\n')
191+
192+
print(f"✅ 已保存 {len(diff_data)} 条差异数据到: {output_file}")
193+
194+
# 显示前几个差异的track_id作为示例
195+
print(f"\n📋 差异track_id示例 (前10个):")
196+
for i, track_id in enumerate(list(diff_track_ids)[:10], 1):
197+
print(f" {i}. {track_id}")
198+
199+
if len(diff_track_ids) > 10:
200+
print(f" ... 还有 {len(diff_track_ids) - 10} 个")
201+
202+
except Exception as e:
203+
print(f"❌ 保存文件时出错: {e}")
204+
return
205+
206+
print("\n" + "=" * 80)
207+
print("🎉 比较完成!")
208+
print("=" * 80)
209+
210+
if __name__ == "__main__":
211+
main()

0 commit comments

Comments
 (0)