发现我的不足:
1、对awt和swing的使用十分的差劲,时不时就要查一下博客。。。
可以做一个专门爬取网页图片的软件,功能已经实现了,就UI对应的设计一下就好了。
做完了。。虽然有很大的局限,但是功能和界面是有的
Main.java
package crawling.app;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Main
{
//写一个界面
JFrame frame = new JFrame("图片爬取器");
JLabel pathlabel = new JLabel("当前保存路径:.");
JLabel show = new JLabel();
public static void main(String[] args) throws Exception
{
//先把功能写出来。然后在写GUI,这样清晰的多,也容易做
//以豆瓣的电影排行榜为例
//我打算先把对应网页直接整个爬下来。存入文本
//然后在在本地进行正则分析,存入excel和JDBC
/*
//创建一个Crawling对象
Crawling craw = new Crawling("https://movie.douban.com/chart");
craw.getContent("E:\\java\\practice\\seven\\Java爬虫练习\\豆瓣电影排行榜网页源代码.txt");
//我需要电影封面的url、电影名称、上映年份、演员表、评分、评价人数
craw.analysis();//爬取图片url
*/
Main main = new Main();
main.init();
}
public void init()
{
frame.setSize(800,600);
JPanel panel = new JPanel();//用来放网址提示和输入框
JLabel label = new JLabel("网址:");
panel.add(label);
JTextField web = new JTextField(40);
panel.add(web);
frame.add(panel, BorderLayout.NORTH);
JPanel panel2 = new JPanel();
JButton crawBn = new JButton("开始爬取");
JButton selectPathBn = new JButton("选择位置");
panel2.add(selectPathBn);
panel2.add(crawBn);
frame.add(panel2,BorderLayout.SOUTH);
JPanel panel3 = new JPanel(new BorderLayout());
panel3.add(pathlabel,BorderLayout.NORTH);
panel3.add(show,BorderLayout.CENTER);
frame.add(panel3,BorderLayout.CENTER);
JFileChooser chooser = new JFileChooser(".");
chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES);
Action selectFile = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
int result = chooser.showOpenDialog(new JFileChooser("."));
if(result == JFileChooser.APPROVE_OPTION)
{
String name = chooser.getSelectedFile().getPath();
pathlabel.setText("当前路径:"+name);
}
}
};
selectPathBn.addActionListener(selectFile);
Action crawling = new AbstractAction()
{
public String url;
public void actionPerformed(ActionEvent e)
{
new Thread(() -> {
url = web.getText();//用户输入的网址
CrawPictures craw = new CrawPictures(url,show);
craw.analysis(pathlabel.getText().split(":")[1]+"\\");
}).start();
}
};
crawBn.addActionListener(crawling);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
}
CrawPictures.java
package crawling.app;
import java.net.*;
import java.util.*;
import java.io.*;
import java.util.regex.*;
import org.apache.poi.hssf.usermodel.*;
import javax.swing.*;
public class CrawPictures
{
/**
* 网站的网址
*/
private String web;
/**
* URL
*/
private URL url;
/**
* URL与网站连接
*/
private URLConnection conn;
/**
* 网页源代码
*/
private String sourcecode;
/**
* 传递过来一个对象
*/
private JLabel show;
/**
* Crawling的构造器
* @param web 网站的网址
*/
public CrawPictures(String web, JLabel show)
{
this.web = web;
this.show = show;
try
{
url = new URL(web);
conn = url.openConnection();
//设置请求头,伪装成浏览器
conn.setRequestProperty("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64)"+
" AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36");
conn.connect();
}
catch(Exception e)
{
e.printStackTrace();
}
//System.out.println("这里是Crawling的构造器");
}
//实例初始化块 ,实例初始化块比构造器更早执行。。。
{
//System.out.println("这里是Crawling的实例初始化块");
}
/**
* 获取网页源代码,直接下载到本地的指定路径里面
* @param path 本地路径,保存网页源代码
* @return 同时将网页源代码以文本形式返回
*/
private String getContent(String path)
{
//打算采用字符流
String msg = "";
try(
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(),"utf-8"));
PrintStream ps = new PrintStream(new File(path))
)
{
String line = null;
int count = 0;
while((line = br.readLine())!=null)
{
msg+=line;
ps.println(line);
count++;
/*
try{
Thread.sleep(1000);
}
catch(Exception e)
{
e.printStackTrace();
}
*/
System.out.println("已下载:"+count+"行");
show.setText("已下载:"+count+"行");
}
System.out.println("爬取网页源代码完成!");
show.setText("爬取网页源代码完成!");
}
catch(IOException ioe)
{
ioe.printStackTrace();
}
sourcecode = msg;
return msg;
}
/**
* 通过用户输入的一段内容进行分析,然后生成对应的正则表达式<br>
* 1、 用户输入的用例那里替换成(.*?) 先试一下
* 2、所有\s匹配的地方,替换成\\s*
* 3、
*/
/**
* 分析网页源代码的方法,取出我所需要的字段,将他们放在ArrayList中
*/
public void analysis(String path)
{
//先把网页源代码爬下来
getContent(path+"网页源代码.txt");
//存储爬取图片链接用的ArrayList<String>
ArrayList<String> pictures = new ArrayList<>();
//电影的封面url
String pic_regex = "<img src=\"(https:.*?\\.jpg)\".*?/>";
getDataById(pic_regex,pictures);//提取出图片的url
//下载电影封面
getPicture(pictures,path);
}
/**
* 这是一个用正则表达式提取数据的方法,方便复用,只需要传入正则表达式的模式,和存储用的ArrayList<String>
* @param regex 匹配用的正则表达式
* @param list 存储数据用的ArrayList<String>
*/
private void getDataById(String regex,ArrayList<String> list)
{
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(sourcecode);
int i = 0;
//第一种方式,一个字段一个字段来
while(m.find())
{
int groupCount = m.groupCount();
String elements = "";
for( int j = 0; j < groupCount;j++)
{
String element = m.group(j+1);//获取匹配对象
if(j==groupCount-1)
{
elements+= element;
}
else
{
elements += element+":";
}
}
list.add(elements);//存入ArrayList<String>中
i++;
System.out.println("正在爬取第"+i+"个,请稍等..."+elements);
show.setText("正在爬取第"+i+"个,请稍等..."+elements);
}
System.out.println("所有元素爬取完成,共"+i+"个");
show.setText("所有元素爬取完成,共"+i+"个");
//另一种方式pattern中是一大串,用group(1),group(2)这样来爬取。
}
/**
* 根据封面url爬取图片
* @param pictures 存储图片url的ArrayList<String>
*/
private void getPicture(ArrayList<String> pictures,String savepath)
{
int i;
for(i = 0 ; i < pictures.size(); i++)
{
try{
String path = pictures.get(i);
String name = path.split("/")[path.split("/").length-1];
System.out.println("正在下载第"+(i+1)+"张图片,请稍等..."+name);
show.setText("正在下载第"+(i+1)+"张图片,请稍等..."+name);
URL url = new URL(path);
URLConnection conn = url.openConnection();
conn.setRequestProperty("user-agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64)"+
" AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36");
conn.connect();
//字节流
InputStream input = conn.getInputStream();
byte[] buffer = new byte[1024];
int hasRead = -1;
RandomAccessFile raf = new RandomAccessFile(savepath+name,"rw");
while((hasRead = input.read(buffer)) != -1)
{
raf.write(buffer,0,hasRead);
}
input.close();
raf.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
System.out.println("图片下载完成,共"+i+"张");
show.setText("图片下载完成,共"+i+"张");
}
}