[0403]学习一个——苟(简单Java开发)

学习一个——苟

1. 开发目的


  • 拜读了某神犇的blog,感到了自身深深的不足。蒟蒻如我,决定提高一蛤自身的姿势水平,学习一个,使用Java重写用GreatestLanguage写的某小说网站的抓取器

2. 分析&实现


2.1 Gui

  • 因为有之前帮国外小老板写java作业的经验:
    • 他object的PDF上实现效果是这样:
    • 我实现的弱鸡效果是这样:
    • 使用GridLayout实现的代码:
guiFrame =new JFrame("龙弟弟");
		guiFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		guiFrame.setLocation(400, 200);
		
		JPanel panel=new JPanel(new GridLayout(0,8));
		for(int i=0;i<64;++i) {
			Color tmp=new Color((int)(1+Math.random()*255),(int)(1+Math.random()*255),(int)(1+Math.random()*255));
			arrayLabels[i]=new ColorLabel(40,40,tmp);
			panel.add(arrayLabels[i]);	
		}
		
		GridBagLayout gridbag = new GridBagLayout();
        GridBagConstraints c = new GridBagConstraints();
        guiFrame.setLayout(gridbag);
        c.weightx = 1.0;
        c.weighty = 1.0;
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.gridheight = 1;
		gridbag.setConstraints(panel, c);
        guiFrame.add(panel);
        
        JButton b = new JButton("Press me to refresh labels");	
        Dimension preferredSize = new Dimension(320,40);
		b.setPreferredSize(preferredSize);
		b.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent arg0) {
				for(int i=0;i<64;++i) {
					Color tmp=new Color((int)(1+Math.random()*255),(int)(1+Math.random()*255),(int)(1+Math.random()*255));
					arrayLabels[i].SetDrawColor(tmp);
				}
				guiFrame.setTitle("LDD");
				guiFrame.repaint();
			}  
			
		});
		guiFrame.add(b);
		
		guiFrame.setVisible(true);
		guiFrame.setSize(guiFrame.getPreferredSize());
+ emmm这也算是用GridLayout完成了
  • 所以这次我熟练了!GridLayout垃圾!EmptyBorder最高!
    • 我设想的是这样:
    • 最后做出来是这样:
    • Code:
public Gui() {
		setTitle("苟");
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
		setSize(350,400);
		Font f = new Font("微软雅黑", Font.BOLD, 18); 
		UIManager uiManager=new UIManager();
		uiManager.put("Label.font", f); 
		uiManager.put("TextField.font", f); 
		uiManager.put("TextField.setColumns", 1); 
		uiManager.put("TextArea.font", f); 
		uiManager.put("Button.font", f); 
		uiManager.put("RadioButton.font", f);
		JPanel content;
		content = new JPanel();
	    content.setBackground(SystemColor.controlHighlight);
	    content.setBorder(new EmptyBorder(5, 5, 5, 5));
	    setContentPane(content);
	    content.setLayout(null);
	    
		JLabel label1=new JLabel("网址:");
		label1.setBounds(15, 10, 100, 30);
		content.add(label1);
		
		JTextField textField1 = new JTextField();
	    textField1.setColumns(1);
	    textField1.setBounds(115, 10, 180, 30);
	    content.add(textField1);
	    
	    JLabel label2=new JLabel("保存地址:");
		label2.setBounds(15, 45, 100, 30);
		content.add(label2);
		
		JTextField textField2 = new JTextField("E://");
	    textField2.setBounds(115, 45, 180, 30);
	    content.add(textField2);
	    
	    JLabel label3=new JLabel("线程数:");
		label3.setBounds(15, 80, 100, 30);
		content.add(label3);
		
		JTextField textField3 = new JTextField("20");
	    textField3.setBounds(115, 80, 30, 30);
	    content.add(textField3);
	    textField3.addKeyListener(new KeyAdapter() {
	    	public void keyTyped(KeyEvent e) {
				int keyChar = e.getKeyChar();				
				if(keyChar >= KeyEvent.VK_0 && keyChar <= KeyEvent.VK_9){
					
				}else{
					e.consume(); 
				}
			}
		});
	    
	    JLabel label4=new JLabel("检查间隔/s:");
		label4.setBounds(150, 80, 130, 30);
		content.add(label4);
		
		JTextField textField4 = new JTextField("1");
	    textField4.setBounds(265, 80, 30, 30);
	    content.add(textField4);
	    
	    JLabel label5=new JLabel("过滤规则:");
		label5.setBounds(15, 115, 130, 30);
		content.add(label5);
		
	    JTextArea textArea1 = new JTextArea();
	    JScrollPane scrollPane=new JScrollPane(textArea1);
	    scrollPane.setBounds(15, 150, 120, 180);
	    scrollPane.setHorizontalScrollBarPolicy(
	    		JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
	    scrollPane.setVerticalScrollBarPolicy(
	    		JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
	    content.add(scrollPane);
	    
	    JRadioButton radiobutton1=new JRadioButton("完成时打开",true);
	    radiobutton1.setBounds(160, 115, 130, 30);
	    content.add(radiobutton1);
	    
	    JTextArea textArea2 = new JTextArea();
	    textArea2.setBounds(160, 150, 130, 130);
	    content.add(textArea2);
	    
	    JButton button1 = new JButton("Do it!");
	    button1.setBounds(160, 300, 130, 30);
	    
	    button1.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				JOptionPane.showMessageDialog(Gui.this,"开始抓取!");
			}
		});
	    
	    content.add(button1);
	}
+ 所以Java跟GreatestLanguage对像素的定义居然不一样???
+ 抄(划)用到的姿势:
    * [文本框添加滚动条](https://blog.csdn.net/xueerfei008/article/details/36006961)
    * [批量设置控件属性](https://blog.csdn.net/yjqyyjw/article/details/52301963)
    * [文本框只允许输入数字](https://blog.csdn.net/lanjianhun/article/details/8273453)
+ 未实现的:
    * 文本框加上调节器,Java似乎没有这个控件,需要手动实现

2.2 HTTP读文本&正则取出文本中间内容

  • Java没有封装HTTP读文本类肿么办!不怕!抄(划掉)学习一个!不会正则肿么办,emmmmm,只有学习一个了。
  • 一开始抄的HTTP读文本蜜汁不支持读网页端的笔趣阁,只能读wap端口的
    • wap端口的目录一个网页只有20章
    • 要翻页获取
    • 每次下一页所在的标签都不是用一个位置
    • 第一页和最后一页要特殊定义
    • 然后我都实现了!
String bookurl="http://m.b5200.net"+UrlList.get(2);
List<String> allurl = new ArrayList();
List<String> allna = new ArrayList();
List<String> NameList;
//获取正序目录
content = getHtmlContent(bookurl);
regex =  "<a[^>]*href="/wapbook-[^>]*>.*?</a>";
link = getContentByRegex(content,regex);
UrlList = match(link.toString(), "a", "href");  
bookurl="http://m.b5200.net"+UrlList.get(0);
String endurl="http://m.b5200.net"+UrlList.get(2);
//访问正序目录
//boolean first=true;
/*while(bookurl!=endurl) {
	System.out.println(bookurl);
	content = getHtmlContent(bookurl);
  regex =  "<a[^>]*href="/wapbook-[^>]*>.*?</a>";
  link = getContentByRegex(content,regex);
  UrlList = match(link.toString(), "a", "href");  
  //System.out.println(UrlList);
  if(first){first=false;bookurl="http://m.b5200.net"+UrlList.get(2);}
  else {bookurl="http://m.b5200.net"+UrlList.get(4);}
  regex =  "<a[^>]*href='/wapbook-[^>]*>.*?</a>";
  link = getContentByRegex(content,regex);
  UrlList = match(link.toString(), "a", "href");  
  NameList = getLabelValues(link.toString(),regex);   
  allurl.addAll(UrlList);
  allna.addAll(NameList);
+ 最后发现wap端容易崩,单线程读5次目录就502了……Orz,只能重写
  • 重写之后,可以完美读PC端内容了!
    • Java的格式化代码总是出现奇奇怪怪的排版
	public static List<Map<String, String>> getbook(String urlNameString) {
		List<Map<String, String>> reqMap = new ArrayList<Map<String, String>>();
		try {
			String content = getHtmlContent(urlNameString);
			System.out.println(getTitle(content));
			// 获取小说信息的结果
			String regex = "<a[^>]*href="" + urlNameString + "[^>]*>.*?</a>";
			List<String> link = getContentByRegex(content, regex);// 包含标签的地址
			List<String> UrlList = match(link.toString(), "a", "href"); // 每章Url地址
			List<String> NameList = getLabelValues(link.toString(), regex); // 每章标题
			//System.out.println("NameList:" + NameList.get(0));
			//getchapter(UrlList.get(0));

		} catch (Exception e) {
			e.printStackTrace();
		}

		return reqMap;
	}
	private static String getchapter(String Url) {
		StringBuilder chapter = new StringBuilder();
		try {
			String content = getHtmlContent(Url);
			String regex = "<div id="content">[^>]*>.*?</div>";

			List<String> tmp = getContentByRegex(content, regex);
			List<String> tmp2 = getLabelValues(tmp.toString(), regex);
			String tmp3 = tmp2.get(0);
			System.out.println(tmp3);
			String[] array = tmp3.split("  ");
			for (String str : array) {
				chapter.append(str).append("
");
			}
			// System.out.println(chapter.toString());

		} catch (Exception e) {
			e.printStackTrace();
		}
		return chapter.toString();
	}
+ 美丽的测试输出:

2.3 天国的多线程

  • 由于我太弱,研究一晚上仍未找到跨类调用的方法,比如说在Thread类中调用GUI类中定义的Re类中的某个项-、-
  • 还比如如何在Thread类中修改GUI类中定义的JFrame中的参数,比如说
Thread extends Gui{
……
super.setTitle();
super.TextArea1.setFront();
  • 都是不合法的…战略性放弃,改日再战。
  • 本来写的检查间隔是用来设置一个clock来监控操作是否完成强行结束线程防止溢出的,现在成了摆设=、=
  • 还是易语言写多线程&图形化编程简单啊…

2.4 获取章节内容并输出

  • 速度极慢的还得等待防止502的单线程:
                                        FileWriter fw = new FileWriter(SaveAddress, true);
					BufferedWriter bw = new BufferedWriter(fw);  
					bw.append(getTitle()+"
");
					for(int i=0;i<a.num;++i) {
						bw.append(a.NameList.get(i)+"
");
						textArea2.append(a.NameList.get(i)+"
");
						bw.append(a.getchapter(i));
						System.out.println(a.NameList.get(i));
						Thread.currentThread().sleep(1000);
					}
					bw.close();
					fw.close();
  • 最终效果:,也算是基本实现了功能

2.5 完成时打开文件夹

  • 似乎有runtime.exec("explorer /select, " + yourFileOrFolderLocation); 这种神奇的操作,但我没有实现。
  • code:
if(radiobutton1.isSelected())
					try {
			            java.awt.Desktop.getDesktop().open(new File(SaveAddress));
			        } catch (IOException e2) {
			            e2.printStackTrace();
			        }

3. 后记


  • 也算是Java写的第一个具有一定应用价值的桌面化程序,已发布在Github
  • 代码书写格式仍有许多不足,大抵是平时练习过少导致的,也有少部分是因为OI带来的历史遗留问题,只考虑完成算法-》完美运行,没有考虑到后续维护。
  • 懒,没写纯字符串的文本_取出中间文本,文本_去中间_批量,大概会比正则快上那么一点?主要是Java调用不了易语言写的DLL,太遗憾了。
  • 最后跟我念:”E is the Greatest Language!"
原文地址:https://www.cnblogs.com/shy-/p/8709399.html