试了一下用Java写爬虫,确实不如python写起来简单。
URLConnection类
转自:URLConnection类,HttpURLConnection类的使用和总结
抽象类 URLConnection 是所有类的超类,它代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源。URLConnection 基于Http协议。通常,创建一个到 URL 的连接需要几个步骤:
- 通过在 URL 上调用 openConnection 方法创建连接对象。
- 处理设置参数和一般请求属性。
- 使用 connect 方法建立到远程对象的实际连接。
- 远程对象变为可用。远程对象的头字段和内容变为可访问。
-URLConnection的connect()函数,实际上只是建立了一个与服务器的tcp连接,并没有实际发送http请求。
无论是post还是get,http请求实际上直到HttpURLConnection的getInputStream()这个函数里面才正式发送出去。
在用POST方式发送URL请求时,URL请求参数的设定顺序是重中之重,
对connection对象的处理设置参数和一般请求属性和写入提交数据都必须要在connect()函数执行之前完成。对outputStream的写提交数据操作,必须要在inputStream的读操作之前。这些顺序实际上是由http请求的格式决定的。
http请求实际上由两部分组成,一个是http头,所有关于此次http请求的配置都在http头里面定义,一个是正文content。connect()函数会根据HttpURLConnection对象的配置值生成http头部信息,因此在调用connect函数之前,就必须把所有的配置准备好。
在http头后面紧跟着的是http请求的正文,正文的内容是通过outputStream流写入的,实际上outputStream不是一个网络流,充其量是个字符串流,往里面写入的东西不会立即发送到网络,而是存在于内存缓冲区中,待outputStream流关闭时,根据输入的内容生成http正文。至此,http请求的东西已经全部准备就绪。在getInputStream()函数调用的时候,就会把准备好的http请求正式发送到服务器了,然后返回一个输入流,用于读取服务器对于此次http请求的返回信息。由于http请求在getInputStream的时候已经发送出去了(包括http头和正文),因此在getInputStream()函数之后对connection对象进行设置(对http头的信息进行修改)或者写入outputStream(对正文进行修改)都是没有意义的了,执行这些操作会导致异常的发生。
HttpURLConnection类是支持 HTTP 特定功能的 URLConnection。每个 HttpURLConnection 实例都可用于生成单个请求,但是其他实例可以透明地共享连接到 HTTP 服务器的基础网络。请求后在 HttpURLConnection 的 InputStream 或 OutputStream 上调用 close() 方法可以释放与此实例关联的网络资源,但对共享的持久连接没有任何影响。如果在调用 disconnect() 时持久连接空闲,则可能关闭基础套接字。
URLConnection 是所有类的超类,它代表应用程序和 URL 之间的通信链接。该类的实例可以用来对由 URL 引用的资源进行读取和写入操作。
模式匹配Pattern类和Matcher类
爬取网站的图片,使用正则表达式从网页上匹配出图片的url
java.util.regex.Pattern和java.util.regex.Matcher用于模式匹配的类,模式对象封装了正则表达式。Matcher对象方法则主要针对匹配结果进行处理,下面用代码段示例说明:
String regex = "[a-z] at";
String str = "a fat cat and a rat were eating oat in the vat."
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
while(m.find()){
String s = m.group();
System.out.println(s);
}
关于pattern类和Matcher类有篇博客写的不错。
链接:JAVA正则表达式:Pattern类与Matcher类详解
下面是爬虫的代码:
package sp;
import java.io.*;
import java.net.*;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class spider {
public static void main(String[] args) {
String address ="http://www.netbian.com/index.htm";
System.out.println("爬取http://www.netbian.com图片");
System.out.println("图片将保存至d:/java/picture");
System.out.println("请输入从第几页开始爬取:");
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
System.out.println("爬取页数:");
int m = scanner.nextInt();
if (n <1) {
System.out.println("页码小于1");
System.exit(0);
}else if(n > 1) {
String snum = String.valueOf(n);
address = "http://www.netbian.com/index_"+snum+".htm";
}
for(;m>=1;m--) {
String h = getHtm(address);
//提取图片url
Pattern imgpattern=Pattern.compile("http://img\\.netbian\\.com/file/.*?\\.jpg");
Matcher imgmatcher=imgpattern.matcher(h);
while (imgmatcher.find()){
String imgString=imgmatcher.group();
String[] strs=imgString.split("/");
String name = strs[strs.length-1];
String path = "d:/java/picture/"+name;
downloadPicture(imgString,path);
//更新下一页address
String snum = String.valueOf(n+1);
address = "http://www.netbian.com/index_"+snum+".htm";
}
}
}
private static String getHtm(String address){
HttpURLConnection conn = null;
URL url = null;
InputStream in = null;
BufferedReader reader = null;
StringBuffer stringBuffer = null;
try {
url = new URL(address);
conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setReadTimeout(5000);
conn.setDoInput(true);
conn.connect();
in = conn.getInputStream();
reader = new BufferedReader(new InputStreamReader(in));
stringBuffer = new StringBuffer();
String line = null;
while((line = reader.readLine()) != null){
stringBuffer.append(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally{
conn.disconnect();
try {
in.close();
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return stringBuffer.toString();
}
private static void downloadPicture(String imageurl,String path) {
try {
URL url = new URL(imageurl);
DataInputStream dataInputStream = new DataInputStream(url.openStream());
FileOutputStream fileOutputStream = new FileOutputStream(new File(path));
ByteArrayOutputStream output = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = dataInputStream.read(buffer)) > 0) {
output.write(buffer, 0, length);
System.out.println(imageurl);
}
fileOutputStream.write(output.toByteArray());
dataInputStream.close();
fileOutputStream.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}