图书整理系统(3)--对图书进行移动

到了本系统的重点环节;

主要分为三步走:

1.获取所有图书

    查询图书,图书名称,原图书位置,对图书名称进行处理,方便网站查询提高命中率

2.填充图书类型,根据图书名称获取图书列表,然后获取图书的详细内容中的图书类型编码,然后根据图书类型编码获取本地图书路径

3.根据图书源路径,目的路径移动图书

代码如下:

package com.gugu.book;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;

public class MoveBook {
	
	// 源文件储存基本路径
	static String directoryPath = "F:\\book";
	private static String sepa = java.io.File.separator;
	// 图书查询失败(网站中图书不存在)
	static int errCount = 0;
	static Map<String, String> bookTypeMap = new HashMap<String, String>();
	
	public static void main(String[] args) {
		
		// 获取所有书名
		List<Book> bookList = getAllBook(directoryPath);
		// 获取图书分类号,清洗过图书列表
		List<Book> bookList2 = filedBookTypeList(bookList);
		// 根据图书类型编号,获取图书需要迁移的路径
		List<Book> bookList3 = filedBookTargetPathList(bookList2);
		copyFile(bookList3);
		
	}
	
	/**
	 * 
	 * @Title: copyFile 
	 * @Description:  将图书文件复制到对应路径下
	 * @param bookList: 
	 * void
	 */
	private static void copyFile(List<Book> bookList) {
		
		for(Book b : bookList) {
			String sourcePath = b.getSourcePath();
			String targetPath = b.getTargetPath(); // 没有包含文件名
			
			if(targetPath != null) {
				try {
					String targetFileName = targetPath + sepa + b.fileName; // 添加文件名称
					Files.copy(new File(sourcePath).toPath(), new File(targetFileName).toPath());
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * 
	 * @Title: filedBookTargetPathList 
	 * @Description: 填充图书目的地址
	 * @param bookList 图书列表
	 */
	private static List<Book> filedBookTargetPathList(List<Book> bookList) {
		List<Book> bookResultList = new ArrayList<Book>();
		
		getBookTypePathMap(bookList);
		for(Book b : bookList) {
			String typeCode = b.getTypeCode();
			
			if(bookTypeMap.containsKey(typeCode) && typeCode != null) {
				
				b.targetPath = bookTypeMap.get(typeCode);
				bookResultList.add(b);
			}else {
				// 图书归类失败
				System.out.println("图书归类失败:" + b.toString());
			}
			
		}
		
		return bookResultList;
	}
	
	/**
	 * 
	 * @Title: getBookTypePathMap 
	 * @Description: 根据图书类型获取图书需要迁移的路径
	 * @param bookList: 
	 * void
	 */
	private static void getBookTypePathMap(List<Book> bookList) {
		
		for (Book book : bookList) {
			String bookCode = book.typeCode;
			if(!bookTypeMap.containsKey(bookCode) && bookCode != null){
				String typePath = findTargetPath(bookCode);
				if(typePath == null) {
					// 查询分类路径失败
					System.out.println("查询分类路径失败:"+bookCode);
				}else {
					System.out.println("分类" + bookCode + ",分类路径:"+typePath);
					bookTypeMap.put(bookCode, typePath);
				}
			}
		}
	}

	/**
	 * 
	 * @Title: findTargetPath 
	 * @Description: 根据图书类别查询图书路径,由于网站获取图书类别编码比较详细,分类中没有那么详细的分类,使用模糊匹配,并且截取最后一位
	 * @param bookCode
	 * @return: 
	 * String
	 */
	private static String findTargetPath(String bookCode){
		String typePath = null;
		String typeBasePath = "E:\\book";
		List<String> typePathList =  getAllTypeContent(typeBasePath);
		//截取最后一位判断是否有分类
		while(bookCode.length() > 0) {
			for (String path : typePathList) {
				if(path.contains(bookCode)) {
					return path;
				}
			}
			// 截取字符串
			bookCode = bookCode.substring(0, bookCode.length()-1);
		}
		return typePath;
	}
	
	/**
	 * 
	 * @Title: getAllTypeContent 
	 * @Description: 获取图书分类内容,原先已经创建好的路径
	 * @param typeBasePath
	 * @return: 
	 * List<String>
	 */
	private static List<String> getAllTypeContent(String typeBasePath){
		List<String> typePathList = new ArrayList<>();
		
		File baseFile = new File(typeBasePath);
        if (baseFile.isFile() || !baseFile.exists()) {
            return null;
        }
        File[] files = baseFile.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
            	typePathList.add(file.getAbsolutePath());
            	typePathList.addAll(getAllTypeContent(file.getAbsolutePath()));
            } 
        }
		return typePathList;
	}

	/**
	 * 
	 * @Title: filedBookTypeList 
	 * @Description: 填充图书类型
	 * @param bookList
	 * @return: 
	 * List<Book>
	 */
	private static List<Book> filedBookTypeList(List<Book> bookList) {
		List<Book> bookResultList = new ArrayList<Book>();
		
		for (Book book : bookList) {
			
			String bookName = book.getName();
			String bookTypeCode = getBookTypeCode(bookName);
			if(null != bookTypeCode) {
				book.setTypeCode(bookTypeCode);
				bookResultList.add(book);
//				System.out.println("查询图书:" + bookName+",编码:"+ bookTypeCode);
			}else {
				errCount++;
//				System.out.println("查询图书类型失败:" + bookName);
			}
		}
		System.out.println(errCount);
		
		return bookResultList;
	}
	
	// 模拟浏览器抓取图书信息,第一次获取图书列表,第二次获取图书内容(主要是图书类型)
	private static String getBookTypeCode(String bookName) {
		String bookTypeCode = null;
		// 获取检索的图书列表
		String url = "http://find.nlc.cn/search/doSearch?"
				+ "query=" + bookName + "&"
				+ "secQuery=&"
				+ "actualQuery=" + bookName + "&"
				+ "searchType=2&"
				+ "docType=%E5%85%A8%E9%83%A8&"
				+ "isGroup=isGroup&"
				+ "targetFieldLog=%E5%85%A8%E9%83%A8%E5%AD%97%E6%AE%B5&"
				+ "fromHome=true";
		
		try {
			Document document = Jsoup.connect(url).timeout(3000000).get();
			Element listE = document.getElementById("searchresult-items").selectFirst("a"); // 获取图书列表
			String bookId = listE.attr("onclick").toString().split("', '")[1];
			bookTypeCode = getBookDetailCode(bookName, bookId);
			
		} catch (IOException e) {
			e.printStackTrace();
		}catch (Exception e) {
//			e.printStackTrace();
		}
		
		return bookTypeCode;
	}
	
	
	// 获取图书详细信息
	private static String getBookDetailCode(String bookName, String bookId) {
		String bookTypeCode = null;
		// 获取检索的图书列表
		String url = "http://find.nlc.cn/search/showDocDetails?"
				+ "docId=" + bookId + "&"
				+ "dataSource=ucs01&"
				+ "query="+bookName;
		try {
			Document document = Jsoup.connect(url).timeout(3000000).get();
			Element listE = document.getElementById("detail-info"); // 获取图书列表
			bookTypeCode = listE.toString().split("中图分类")[1].split("<")[0].replace(" ", "").replace(":", "");
			
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return bookTypeCode;
	}

	/**
	 * 
	 * @Title: getAllBook 
	 * @Description: 获取所有图书,并清除特殊字符
	 * @param directoryPath
	 * @return: 
	 * List<Book>
	 */
	public static List<Book> getAllBook(String directoryPath) {
        List<Book> list = new ArrayList<Book>();
        File baseFile = new File(directoryPath);
        if (baseFile.isFile() || !baseFile.exists()) {
            return list;
        }
        File[] files = baseFile.listFiles();
        for (File file : files) {
            if (file.isDirectory()) {
                list.addAll(getAllBook(file.getAbsolutePath()));
            } else {
            	String sourcePath = file.getAbsolutePath();
            	String fileName = file.getName();
            	String bookName = fileName.split(".pdf")[0];
            	// 处理书名包含版本导致查询不到
    			if(bookName.contains("(第")) {
    				bookName = bookName.split("\\(第")[0];
    			}
    			bookName = bookName.replace("(中文版)", "");
    			bookName = bookName.replace("(上册)", "");
    			bookName = bookName.replace("(下册)", "");
    			bookName = bookName.replace("(2)", "");
    			// # 编码导致
    			bookName = bookName.replace("#", "%23");
            	
            	
				Book book = new Book(sourcePath, bookName, fileName);
                list.add(book);
            }
        }
        return list;
    }
	
	
	
}
// 图书类
class Book{
	String sourcePath;// 图书源路径
	String name;// 图书名称
	String fileName;// 文件名
	String typeCode; // 图书类型编码
	String targetPath;// 图书目的路径
	
	
	public Book(String sourcePath, String name, String fileName) {
		super();
		this.sourcePath = sourcePath;
		this.name = name;
		this.fileName = fileName;
	}
	
	public Book(String sourcePath, String name, String fileName, String typeCode, String targetPath) {
		super();
		this.sourcePath = sourcePath;
		this.name = name;
		this.fileName = fileName;
		this.typeCode = typeCode;
		this.targetPath = targetPath;
	}
	
	public String getSourcePath() {
		return sourcePath;
	}

	public void setSourcePath(String sourcePath) {
		this.sourcePath = sourcePath;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public String getTypeCode() {
		return typeCode;
	}

	public void setTypeCode(String typeCode) {
		this.typeCode = typeCode;
	}

	public String getTargetPath() {
		return targetPath;
	}

	public void setTargetPath(String targetPath) {
		this.targetPath = targetPath;
	}

	@Override
    public String toString() {
        return "Book [sourcePath=" + sourcePath + ", name=" + name + ", fileName=" + fileName + ", typeCode=" + typeCode + ", targetPath=" + targetPath + "]";
    }
	
}
   

只不过最终这个项目的方案,我自己否掉了,主要原因如下

1.命中率不高,原本图书中有259本,网站大约有三十本左右是无法查询到的。

2.图书分类并不能十分符合原本意愿,可能是网站比较大,并不是专门为计算机图书定制的,对于部分图书会存在分类不准确的情况。


反思:通过这个项目,发现自己对于项目的估计太过乐观,也反映了,在少数情况下可能会比较正常,但是数据上去之后,很容易就会出现意外,以及自己对项目的把控能力不足的问题。

图书已经手动分类到百度云上:

链接:https://pan.baidu.com/s/1TRXSt_e7o-mUUL_HVgI-sw 密码:uu2q

对图书有兴趣的可以自行下载,对于项目感兴趣的小伙伴可以提出您的建议,那我将不胜感激



猜你喜欢

转载自blog.csdn.net/zhazhagu/article/details/80914987