11/**
22 * 文件操作工具模块
3- *
3+ *
44 * 功能:提供文件读写、路径处理、解析器配置等核心文件操作功能
55 * 包含安全的文件访问控制和路径解析功能
6- *
6+ *
77 * @author drpy
88 * @version 1.0.0
99 */
1010
1111import path from "path" ;
1212import { readFileSync , existsSync , mkdirSync , writeFileSync } from 'fs' ;
1313import { fileURLToPath } from "url" ;
14- import { getSitesMap } from "./sites-map.js" ;
1514import '../libs_drpy/jinja.js'
1615
1716// 获取当前模块的目录路径
1817const __dirname = path . dirname ( fileURLToPath ( import . meta. url ) ) ;
1918
2019// 定义核心路径常量
2120const _data_path = path . join ( __dirname , '../data' ) ; // 数据文件存储路径
22- const _config_path = path . join ( __dirname , '../config' ) ; // 配置文件路径
2321const _lib_path = path . join ( __dirname , '../spider/js' ) ; // 库文件路径
2422
23+ export { getSitesMap } from "./sites-map.js" ;
2524// ES6扩展代码路径和内容
2625const es6JsPath = path . join ( __dirname , '../libs_drpy/es6-extend.js' ) ;
2726/**
@@ -38,62 +37,56 @@ const reqJsPath = path.join(__dirname, '../libs_drpy/req-extend.js');
3837 */
3938export const req_extend_code = readFileSync ( reqJsPath , 'utf8' ) ;
4039
41- /**
42- * 站点映射配置
43- * 从配置路径获取站点映射信息
44- */
45- export const SitesMap = getSitesMap ( _config_path ) ;
46-
4740/**
4841 * 路径操作库
4942 * 提供安全的文件读写和路径操作功能
5043 */
5144export const pathLib = {
5245 basename : path . basename , // 获取文件名
5346 extname : path . extname , // 获取文件扩展名
54-
47+
5548 /**
5649 * 安全读取数据文件
57- *
50+ *
5851 * @param {string } filename - 相对于data目录的文件名
5952 * @returns {string } 文件内容,失败返回空字符串
6053 */
6154 readFile : function ( filename ) {
6255 let _file_path = path . join ( _data_path , filename ) ;
6356 const resolvedPath = path . resolve ( _data_path , _file_path ) ; // 将路径解析为绝对路径
64-
57+
6558 // 安全检查:确保访问路径在允许的数据目录内
6659 if ( ! resolvedPath . startsWith ( _data_path ) ) {
6760 log ( `[pathLib.readFile] no access for read ${ _file_path } ` )
6861 return '' ;
6962 }
70-
63+
7164 // 检查文件是否存在
7265 if ( ! existsSync ( resolvedPath ) ) {
7366 log ( `[pathLib.readFile] file not found for read ${ resolvedPath } ` )
7467 return '' ;
7568 }
76-
69+
7770 return readFileSync ( resolvedPath , 'utf8' )
7871 } ,
79-
72+
8073 /**
8174 * 安全写入数据文件
82- *
75+ *
8376 * @param {string } filename - 相对于data目录的文件名
8477 * @param {string } text - 要写入的文本内容
8578 * @returns {boolean } 写入成功返回true,失败返回false
8679 */
8780 writeFile : function ( filename , text ) {
8881 let _file_path = path . join ( _data_path , filename ) ;
8982 const resolvedPath = path . resolve ( _data_path , _file_path ) ; // 将路径解析为绝对路径
90-
83+
9184 // 安全检查:确保访问路径在允许的数据目录内
9285 if ( ! resolvedPath . startsWith ( _data_path ) ) {
9386 log ( `[pathLib.writeFile] no access for read ${ _file_path } ` )
9487 return '' ;
9588 }
96-
89+
9790 try {
9891 const dirPath = path . dirname ( resolvedPath ) ;
9992 // 检查目录是否存在,不存在则创建
@@ -107,39 +100,39 @@ export const pathLib = {
107100 return false
108101 }
109102 } ,
110-
103+
111104 /**
112105 * 安全读取库文件
113- *
106+ *
114107 * @param {string } filename - 相对于库目录的文件名
115108 * @returns {string } 文件内容,失败返回空字符串
116109 */
117110 readLib : function ( filename ) {
118111 let _file_path = path . join ( _lib_path , filename ) ;
119112 const resolvedPath = path . resolve ( _data_path , _file_path ) ; // 将路径解析为绝对路径
120-
113+
121114 // 安全检查:确保访问路径在允许的库目录内
122115 if ( ! resolvedPath . startsWith ( _lib_path ) ) {
123116 log ( `[pathLib.readLib] no access for read ${ _file_path } ` )
124117 return '' ;
125118 }
126-
119+
127120 // 检查文件是否存在
128121 if ( ! existsSync ( resolvedPath ) ) {
129122 log ( `[pathLib.readLib] file not found for read ${ resolvedPath } ` )
130123 return '' ;
131124 }
132-
125+
133126 return readFileSync ( resolvedPath , 'utf8' )
134127 } ,
135128} ;
136129
137130/**
138131 * 获取解析器配置字典
139- *
132+ *
140133 * 功能:从配置文件中读取解析器列表,支持模板变量替换
141134 * 解析parses.conf配置文件,生成解析器对象数组
142- *
135+ *
143136 * @param {string } host - 主机地址,用于模板变量替换
144137 * @returns {Array } 解析器配置对象数组
145138 */
@@ -148,26 +141,26 @@ export function getParsesDict(host) {
148141 const __dirname = path . dirname ( __filename ) ;
149142 const jx_conf = path . join ( __dirname , '../config/parses.conf' ) ;
150143 let jx_list = [ ] ;
151-
144+
152145 // 检查解析器配置文件是否存在
153146 if ( existsSync ( jx_conf ) ) {
154147 const jx_conf_text = readFileSync ( jx_conf , 'utf-8' ) ;
155148 let jx_conf_content = jx_conf_text . trim ( ) ;
156-
149+
157150 // 准备模板变量字典
158151 let var_dict = {
159- host,
152+ host,
160153 hostName : host . split ( ':' ) . length > 1 ? host . slice ( 0 , host . lastIndexOf ( ":" ) ) : host
161154 } ;
162-
155+
163156 // 使用Jinja模板引擎渲染配置内容
164157 jx_conf_content = jinja . render ( jx_conf_content , var_dict ) ;
165-
158+
166159 // 解析配置行:过滤空行和注释行
167160 const jxs = jx_conf_content . split ( '\n' )
168161 . filter ( it => it . trim ( ) && ! it . trim ( ) . startsWith ( '#' ) )
169162 . map ( it => it . trim ( ) ) ;
170-
163+
171164 // 处理每个解析器配置行
172165 jxs . forEach ( ( jx ) => {
173166 let jx_arr = jx . split ( ',' ) ;
@@ -176,7 +169,7 @@ export function getParsesDict(host) {
176169 let jx_type = jx_arr . length > 2 ? Number ( jx_arr [ 2 ] ) || 0 : 0 ; // 解析器类型
177170 let jx_ua = jx_arr . length > 3 ? jx_arr [ 3 ] : 'Mozilla/5.0' ; // User-Agent
178171 let jx_flag = jx_arr . length > 4 ? jx_arr [ 4 ] : '' ; // 标志位
179-
172+
180173 // 构建解析器对象
181174 let jx_obj = {
182175 'name' : jx_name ,
@@ -186,17 +179,17 @@ export function getParsesDict(host) {
186179 "User-Agent" : jx_ua
187180 } ,
188181 }
189-
182+
190183 // 如果有标志位,添加扩展配置
191184 if ( jx_flag ) {
192185 jx_obj . ext = {
193186 "flag" : jx_flag . split ( '|' )
194187 }
195188 }
196-
189+
197190 jx_list . push ( jx_obj ) ;
198191 } ) ;
199192 }
200-
193+
201194 return jx_list
202195}
0 commit comments