Skip to content

Commit c75b9a4

Browse files
jiaojiaodubaiactions-user
authored andcommitted
add CSRES, resolve #538
1 parent d0b19bf commit c75b9a4

4 files changed

Lines changed: 340 additions & 9 deletions

File tree

CSRES.js

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
{
2+
"translatorID": "ef9b1134-402a-4b91-8a82-507fc56ca9e6",
3+
"label": "CSRES",
4+
"creator": "jiaojiaodubai",
5+
"target": "^https?://(www|doc)\\.csres\\.com",
6+
"minVersion": "5.0",
7+
"maxVersion": "",
8+
"priority": 100,
9+
"inRepository": true,
10+
"translatorType": 4,
11+
"browserSupport": "gcsibv",
12+
"lastUpdated": "2026-06-23 00:27:01"
13+
}
14+
15+
/*
16+
***** BEGIN LICENSE BLOCK *****
17+
18+
Copyright © 2026 jiaojiaodubai<jiaojiaodubai23@gmail.com>
19+
20+
This file is part of Zotero.
21+
22+
Zotero is free software: you can redistribute it and/or modify
23+
it under the terms of the GNU Affero General Public License as published by
24+
the Free Software Foundation, either version 3 of the License, or
25+
(at your option) any later version.
26+
27+
Zotero is distributed in the hope that it will be useful,
28+
but WITHOUT ANY WARRANTY; without even the implied warranty of
29+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30+
GNU Affero General Public License for more details.
31+
32+
You should have received a copy of the GNU Affero General Public License
33+
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
34+
35+
***** END LICENSE BLOCK *****
36+
*/
37+
38+
39+
function detectWeb(doc, url) {
40+
if (url.includes('/detail/')) {
41+
return 'standard';
42+
}
43+
else if (getSearchResults(doc, true)) {
44+
return 'multiple';
45+
}
46+
return false;
47+
}
48+
49+
function getSearchResults(doc, checkOnly) {
50+
const items = {};
51+
let found = false;
52+
const rows = doc.querySelectorAll('tr[title]');
53+
for (const row of rows) {
54+
const code = innerText(row, 'td:nth-child(1) > a[href*="/detail/"]');
55+
const href = attr(row, 'td:nth-child(1) > a[href*="/detail/"]', 'href');
56+
const title = innerText(row, 'td:nth-child(2)');
57+
if (!href || !title) continue;
58+
if (checkOnly) return true;
59+
found = true;
60+
items[href] = [code, title].join(" ");
61+
}
62+
return found ? items : false;
63+
}
64+
65+
async function doWeb(doc, url) {
66+
if (detectWeb(doc, url) == 'multiple') {
67+
const items = await Z.selectItems(getSearchResults(doc, false));
68+
if (!items) return;
69+
for (const url in items) {
70+
await scrape(await requestDocument(url));
71+
}
72+
}
73+
else {
74+
await scrape(doc, url);
75+
}
76+
}
77+
78+
async function scrape(doc, url = doc.location.href) {
79+
const newItem = new Z.Item('standard');
80+
const title = doc.querySelector('table > tbody > tr > td > h3');
81+
if (!title) return;
82+
newItem.title = title.innerText.replace(/(\p{Unified_Ideograph}) (\p{Unified_Ideograph})/gu, '$1 $2');
83+
const tr = title.parentElement.parentElement;
84+
const baseInfo = tr.parentElement.querySelector('tr:nth-child(2) > td:nth-child(2) tr:first-child');
85+
if (baseInfo) {
86+
newItem.number = tryMatch(baseInfo.innerText, /(?<=)[A-Z\d.\s/-]+/);
87+
newItem.status = tryMatch(baseInfo.innerText, /(?<=)\S+/);
88+
}
89+
const subTitles = doc.querySelectorAll('td> table > tbody > tr > td.f14b');
90+
for (const subtitle of subTitles) {
91+
if (subtitle.innerText == '标准简介') {
92+
const td = subtitle.parentElement.parentElement.parentElement.parentElement;
93+
newItem.abstractNote = innerText(td, 'table:nth-child(2)');
94+
break;
95+
}
96+
}
97+
const tbodies = doc.querySelectorAll('td[colspan="2"] tbody tbody');
98+
for (const tbody of tbodies) {
99+
if (tbody.querySelector('.sh14')) {
100+
const raw = {};
101+
const rows = tbody.querySelectorAll('tr');
102+
for (const row of rows) {
103+
const label = innerText(row, 'td:first-child strong').replace(/$/, '');
104+
const value = innerText(row, 'td:nth-child(2)');
105+
raw[label] = value;
106+
}
107+
const data = new Proxy(raw, {
108+
get(tartget, prop) {
109+
const result = tartget[prop];
110+
return result ? result : "";
111+
}
112+
});
113+
newItem.date = ZU.strToISO(data.发布日期);
114+
newItem.publisher = data.出版社;
115+
newItem.url = url;
116+
newItem.setExtra('original-title', data.英文名称);
117+
data.归口单位.split('、').forEach((name) => {
118+
newItem.creators.push({
119+
lastName: name,
120+
creatorType: 'author',
121+
fieldMode: 1
122+
});
123+
});
124+
newItem.attachments.push({
125+
title: 'Snapshot',
126+
document: doc
127+
});
128+
break;
129+
}
130+
}
131+
newItem.complete();
132+
}
133+
134+
function tryMatch(string, pattern, index = 0) {
135+
if (!string) return '';
136+
const match = string.match(pattern);
137+
return match && match[index]
138+
? match[index]
139+
: '';
140+
}
141+
142+
/** BEGIN TEST CASES **/
143+
var testCases = [
144+
{
145+
"type": "web",
146+
"url": "http://www.csres.com/detail/234873.html",
147+
"items": [
148+
{
149+
"itemType": "standard",
150+
"title": "镁及镁合金化学分析方法 第1部分:铝含量的测定",
151+
"creators": [
152+
{
153+
"lastName": "全国有色金属标准化技术委员会(SAC/TC 243)",
154+
"creatorType": "author",
155+
"fieldMode": 1
156+
}
157+
],
158+
"date": "2013-09-06",
159+
"abstractNote": "GB/T13748的本部分规定了镁及镁合金中铝含量的测定方法。\n本部分方法一适用于镁合金(含锆、铍、钍或稀土)中铝含量的测定。测定范围:0.020%~0.300%。\n本部分方法二适用于镁及镁合金(不含钛、锆、铍、稀土)中铝含量的测定。测定范围:0.0030%~0.300%。\n本部分方法三适用于镁合金(不含锆、钍或稀土)中铝含量的测定。测定范围:1.50%~12.00%。",
160+
"extra": "original-title: Chemical analysis methods of magnesium and magnesium alloys—Part 1:Determination of aluminium content",
161+
"libraryCatalog": "CSRES",
162+
"number": "GB/T 13748.1-2013",
163+
"publisher": "中国标准出版社",
164+
"status": "现行",
165+
"url": "http://www.csres.com/detail/234873.html",
166+
"attachments": [
167+
{
168+
"title": "Snapshot",
169+
"mimeType": "text/html"
170+
}
171+
],
172+
"tags": [],
173+
"notes": [],
174+
"seeAlso": []
175+
}
176+
]
177+
},
178+
{
179+
"type": "web",
180+
"url": "http://doc.csres.com/detail/235421.html",
181+
"items": [
182+
{
183+
"itemType": "standard",
184+
"title": "化学品分类和标签规范 第3部分:易燃气体",
185+
"creators": [
186+
{
187+
"lastName": "全国危险化学品管理标准化技术委员会(SAC/TC 251)",
188+
"creatorType": "author",
189+
"fieldMode": 1
190+
}
191+
],
192+
"date": "2013-10-10",
193+
"abstractNote": "GB30000的本部分规定了易燃气体的术语和定义、分类标准、判定逻辑和指导、标签。\n本部分适用于易燃气体按联合国《全球化学品统一分类和标签制度》分类和标签。",
194+
"extra": "original-title: Rules for classification and labelling of chemicals—Part 3:Flammable gases",
195+
"libraryCatalog": "CSRES",
196+
"number": "GB 30000.3-2013",
197+
"publisher": "中国标准出版社",
198+
"status": "现行",
199+
"url": "http://doc.csres.com/detail/235421.html",
200+
"attachments": [
201+
{
202+
"title": "Snapshot",
203+
"mimeType": "text/html"
204+
}
205+
],
206+
"tags": [],
207+
"notes": [],
208+
"seeAlso": []
209+
}
210+
]
211+
},
212+
{
213+
"type": "web",
214+
"url": "http://www.csres.com/s.jsp?keyword=%C8%FD%D4%AA&pageNum=1",
215+
"items": "multiple"
216+
},
217+
{
218+
"type": "web",
219+
"url": "http://doc.csres.com/sort/industry/002006_1.html",
220+
"items": "multiple"
221+
}
222+
]
223+
/** END TEST CASES **/

0 commit comments

Comments
 (0)