package com.brucezee.jspider.parser; import com.alibaba.fastjson.JSON; import com.brucezee.jspider.parser.processor.FieldProcessor; import com.brucezee.jspider.parser.define.FieldDefine; import org.apache.commons.lang3.StringUtils; import org.dom4j.*; import org.dom4j.io.SAXReader; import java.io.File; import java.io.InputStream; import java.io.Reader; import java.lang.reflect.Constructor; import java.util.*; /** * 页面解析定义加载器 * Created by zhoubing on 2016/11/24. */ public class DefineLoader { public static void main(String[] args) { FieldDefine fieldDefine = DefineLoader.getFieldDefine(""); String xml = ""; fieldDefine = DefineLoader.parseFieldDefine(xml); System.out.println(JSON.toJSONString(fieldDefine)); } /** * 从文件中解析xml并获取第一个字段解析定义 * @param path 文件路径 * @return 字段解析定义 */ public static FieldDefine getFieldDefine(String path) { return getFieldDefine(path, null); } /** * 从文件中解析xml并获取第一个字段解析定义 * @param file 文件 * @return 字段解析定义 */ public static FieldDefine getFieldDefine(File file) { return getFieldDefine(file, null); } /** * 从流中解析xml并获取第一个字段解析定义 * @param is 数据流 * @return 字段解析定义 */ public static FieldDefine getFieldDefine(InputStream is) { return getFieldDefine(is, null); } /** * 从Reader中解析xml并获取第一个字段解析定义 * @param reader Reader * @return 字段解析定义 */ public static FieldDefine getFieldDefine(Reader reader) { return getFieldDefine(reader, null); } /** * 从文件中解析xml并获取指定id的字段解析定义 * @param path 文件路径 * @param id 字段解析定义的id * @return 字段解析定义 */ public static FieldDefine getFieldDefine(String path, String id) { return getFieldDefine(new File(path), id); } /** * 从文件中解析xml并获取指定id的字段解析定义 * @param file 文件 * @param id 字段解析定义的id * @return 字段解析定义 */ public static FieldDefine getFieldDefine(File file, String id) { return getFieldDefine(file, null, null, id); } /** * 从流中解析xml并获取指定id的字段解析定义 * @param is 数据流 * @param id 字段解析定义的id * @return 字段解析定义 */ public static FieldDefine getFieldDefine(InputStream is, String id) { return getFieldDefine(null, is, null, id); } /** * 从Reader中解析xml并获取指定id的字段解析定义 * @param reader Reader * @param id 字段解析定义的id * @return 字段解析定义 */ public static FieldDefine getFieldDefine(Reader reader, String id) { return getFieldDefine(null, null, reader, id); } private static FieldDefine getFieldDefine(File file, InputStream inputStream, Reader reader, String id) { Map<String, FieldDefine> defineMap = getFieldDefines(file, inputStream, reader); if (StringUtils.isNotBlank(id)) { return defineMap.get(id); } //如果不指定id,则返回第一个 if (defineMap.size() > 0) { String key = DEFAULT_ID_PREFIX + "0"; if (defineMap.containsKey(key)) { return defineMap.get(key); } return defineMap.entrySet().iterator().next().getValue(); } return null; } /** * 从文件中解析xml返回多个以id为key的字段解析定义映射 * @param path 文件路径 * @return 多个字段解析定义 */ public static Map<String, FieldDefine> getFieldDefines(String path) { return getFieldDefines(new File(path)); } /** * 从文件中解析xml返回多个以id为key的字段解析定义映射 * @param file 文件 * @return 多个字段解析定义 */ public static Map<String, FieldDefine> getFieldDefines(File file) { return getFieldDefines(file, null, null); } /** * 从流中解析xml返回多个以id为key的字段解析定义映射 * @param is 流 * @return 多个字段解析定义 */ public static Map<String, FieldDefine> getFieldDefines(InputStream is) { return getFieldDefines(null, is, null); } /** * 从Reader中解析xml返回多个以id为key的字段解析定义映射 * @param reader Reader * @return 多个字段解析定义 */ public static Map<String, FieldDefine> getFieldDefines(Reader reader) { return getFieldDefines(null, null, reader); } private static Map<String, FieldDefine> getFieldDefines(File file, InputStream inputStream, Reader reader) { SAXReader saxReader = new SAXReader(); Document document = null; try { if (file != null) { document = saxReader.read(file); } else if (inputStream != null) { document = saxReader.read(inputStream); } else if (reader != null) { document = saxReader.read(reader); } else { throw new IllegalArgumentException("all arguments is null"); } } catch (DocumentException e) { throw new IllegalArgumentException(e); } return parseRootElements(document.getRootElement()); } /** * 解析xml文本并获取第一个字段解析定义 * @param xml xml定义 * @return 字段解析定义 */ public static FieldDefine parseFieldDefine(String xml) { return parseFieldDefine(xml, null); } /** * 解析xml文本并获取指定id的字段解析定义 * @param xml xml定义 * @param id 字段解析定义的id * @return 字段解析定义 */ public static FieldDefine parseFieldDefine(String xml, String id) { Map<String, FieldDefine> defineMap = parseFieldDefines(xml); if (StringUtils.isNotBlank(id)) { return defineMap.get(id); } //如果不指定id,则返回第一个 if (defineMap.size() > 0) { String key = DEFAULT_ID_PREFIX + "0"; if (defineMap.containsKey(key)) { return defineMap.get(key); } return defineMap.entrySet().iterator().next().getValue(); } return null; } public static Map<String, FieldDefine> parseFieldDefines(String xml) { Document document = null; try { document = DocumentHelper.parseText(xml); } catch (DocumentException e) { throw new IllegalArgumentException(e); } return parseRootElements(document.getRootElement()); } private static Map<String, FieldDefine> parseRootElements(Element rootElement) { Map<String, FieldDefine> fieldDefineMap = new HashMap<String, FieldDefine>(); if ("defines".equals(rootElement.getName())) { Iterator<Element> rootDefineIterator = rootElement.elementIterator(); int count = 0; while (rootDefineIterator.hasNext()) { count++; Element defineElement = rootDefineIterator.next(); String id = getAttribute(defineElement, "id"); if (StringUtils.isBlank(id)) { id = DEFAULT_ID_PREFIX + count; } if (fieldDefineMap.containsKey(id)) { throw new IllegalArgumentException("duplicated field define id[" + id + "]."); } fieldDefineMap.put(id, parseFieldDefine(defineElement)); } } else if ("define".equals(rootElement.getName())) { String id = getAttribute(rootElement, "id"); if (StringUtils.isBlank(id)) { id = DEFAULT_ID_PREFIX + "0"; } fieldDefineMap.put(id, parseFieldDefine(rootElement)); } else { throw new IllegalArgumentException("xml parse error."); } return fieldDefineMap; } private static final String DEFAULT_ID_PREFIX = "field-define-"; private static FieldDefine parseFieldDefine(Element defineElement) { String type = getAttribute(defineElement, "type"); String name = getAttribute(defineElement, "name"); String selector = getAttribute(defineElement, "selector"); FieldDefine fieldDefine = new FieldDefine(); fieldDefine.setType(type); fieldDefine.setName(name); fieldDefine.setSelector(selector); parseFieldDefines(fieldDefine, defineElement); return fieldDefine; } private static void parseFieldDefines(FieldDefine fieldDefine, Element defineElement) { Iterator<Element> defineIterator = defineElement.elementIterator(); if (defineIterator.hasNext()) { List<FieldDefine> list = new LinkedList<FieldDefine>(); while (defineIterator.hasNext()) { Element element = defineIterator.next(); if ("selector".equals(element.getName())) { fieldDefine.setSelector(element.getText()); } else if ("processor".equals(element.getName())) { fieldDefine.setProcessor(getFieldProcessor(element)); } else { list.add(parseFieldDefine(element)); } } if (list.size() > 0) { fieldDefine.setDefines(list.toArray(new FieldDefine[list.size()])); } } } private static FieldProcessor getFieldProcessor(Element element) { Object[] arguments = getFieldProcessorArguments(element); String clazz = getAttribute(element, "class"); try { if (arguments == null || arguments.length == 0) { return (FieldProcessor) Class.forName(clazz).newInstance(); } Constructor<?>[] constructors = Class.forName(clazz).getConstructors(); for (Constructor<?> constructor : constructors) { if (arguments.length == constructor.getParameterCount()) { return (FieldProcessor) constructor.newInstance(arguments); } } } catch (Exception e) { throw new RuntimeException(e); } return null; } private static Object[] getFieldProcessorArguments(Element element) { Iterator<Element> iterator = element.elementIterator(); List<Object> list = new LinkedList<Object>(); if (iterator.hasNext()) { while (iterator.hasNext()) { list.add(iterator.next().getText()); } } return list.toArray(new Object[list.size()]); } private static String getAttribute(Element element, String name) { Attribute attribute = element.attribute(name); return attribute != null ? attribute.getValue() : null; } }