• [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!"
  • 相关阅读:
    网站页面性能优化的 34条黄金守则 (雅虎团队经验)
    进程调度算法小结
    玩转TCP连接
    数据包在网络中的流转
    浅入理解JVM虚拟机
    Leecode no.47 全排列 II
    Leecode no.143 重排链表
    关于我用设计模式对公司代码重构的这件事
    进程间通信方式小结
    Leecode no.82 删除排序链表中的重复元素 II
  • 原文地址:https://www.cnblogs.com/shy-/p/8709399.html
Copyright © 2020-2023  润新知