最近学习了一下爬虫,发现Java真的是一门强大的语言,方方面面。
1. 爬虫一
指定一个网站,通过正则表达式对服务器返回的数据进行匹配,将符合的信息保存在本地。
/**
* 用Java实现爬虫
* @author aa
*
*/
public class Robot {
public static void main(String[] args){
URL url = null;
URLConnection urlconn = null;
BufferedReader br = null;
PrintWriter pw = null;
// 正则表达式
String regex = "https://[\\w+\\.?/?]+\\.[A-Za-z]+";
Pattern p = Pattern.compile(regex);
try{
url = new URL("https://www.rndsystems.com/cn");
urlconn = url.openConnection();
pw = new PrintWriter(new FileWriter("F:/SiteURL.txt"), true);
br = new BufferedReader(new InputStreamReader(
urlconn.getInputStream()));
String buf = null;
while((buf = br.readLine())!=null){
Matcher buf_m = p.matcher(buf);
while(buf_m.find()){
pw.println(buf_m.group());
}
}
System.out.println("爬取成功");
}catch (MalformedURLException e) {
e.printStackTrace();
}catch (IOException e) {
e.printStackTrace();
}finally{
try{
br.close();
}catch(IOException e){
e.printStackTrace();
}
pw.close();
}
}
}
2. 爬虫二
这个爬虫就更为复杂一些,首先我们指定一个URL,然后对爬取数据进行筛选,将数据中的URL提取出来,重复进行爬取(简单讲,这就是一个循环爬取网页中的网址的爬虫)。为了保证爬取的网站不重复且爬取网站不遗漏,我们创建两个list集合:listOfPendingURLs存放将要爬取的url、listOfTraversedURL是存放已爬取的url。(具体实现详见代码)
/**
* Java实现爬虫二
* @author aa
*
*/
public class WebCrawler {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter a URL:");
String url = input.nextLine();
craweler(url);
}
/**
* 对指定的url进行爬取
* @param url
*/
private static void craweler(String url) {
ArrayList<String> listOfPendingURLs = new ArrayList<>();
ArrayList<String> listOfTraversedURLs = new ArrayList<>();
// 将起始的URL添加到listOfPendingURLs,然后处理其中的每一个url
listOfPendingURLs.add(url);
while(!listOfPendingURLs.isEmpty() && listOfTraversedURLs.size() <= 100){
// 将列表中的第一个URL去除,如果该URL没有被处理过则对其进行处理
String urlString = listOfPendingURLs.remove(0);
if(!listOfTraversedURLs.contains(urlString)){
listOfTraversedURLs.add(urlString);
System.out.println("Crawling: c"+urlString);
// 将页面中每个不存在listOfTraversedURLs中的url添加到listOfPendingURLs中
for (String s : getSubURLs(urlString)) {
if(!listOfTraversedURLs.contains(s))
listOfPendingURLs.add(s);
}
}
}
}
/**
* 该方法为每个给定的url返回一个url列表
* @param urlString
* @return
*/
private static ArrayList<String> getSubURLs(String urlString) {
ArrayList<String> list = new ArrayList<>();
try{
URL url = new URL(urlString);
Scanner input = new Scanner(url.openStream());
int current = 0;
while(input.hasNext()){
String line = input.nextLine();
current = line.indexOf("http:", current);
while(current > 0){
int endIndex = line.indexOf("\"", current);//假设URL以引号"结束
if(endIndex > 0){
list.add(line.substring(current, endIndex));//一行中可能包含多个url
current = line.indexOf("http:", endIndex);//继续寻找下一个URL
}else{
current = -1; //如果该行没有发现URL,current设为-1
}
}
}
}catch(Exception e){
System.out.println("Error"+e.getMessage());
}
return list;//以列表的形式返回
}
}
给与的爬虫终止条件是爬取URL超过100条。
3. 爬虫三
根据输入的URL,爬取其页面上的图片。
程序中使用了httpclient和commons-lang等相关包,我们使用maven进行导入。
maven依赖:
<!-- httpclient -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>${httpclient.version}</version>
</dependency>
<!-- Apache工具组件 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
/**
* Java实现爬虫三 功能: 从一个网址上爬取图片,然后重命名保存到本地路径中
*
* @author aa
*
*/
public class DownloadImageUtil {
// 图片保存路径
public static final String IMAGE_SAVE_PATH = "F:\\image\\DownloadImageUtil";
// 获取img标签正则表达式
public static final String IMGURL_REG = "<img.*src=(.*?)[^>]*?>";
// 获取src路径的正则表达式
public static final String IMGSRC_REG = "(http|https):\"?(.*?)(\"|>|\\s+)";
public static final String[] IMAGE_TYPE_SUFFIX = new String[] { "=png", "=jpg", "=jpeg", ".png", ".jpg", "jpeg" };
// 默认生成的图片名称从1开始递增
public static Integer imageIndex = 1;
public static void main(String[] args) {
// 爬取的网页url
String rquestURL = null;
Scanner sc = new Scanner(System.in);
System.out.println("请输入一个URL地址:");
rquestURL = sc.nextLine();
// 通过请求url解析出相应内容
String htmlContent = ParserContext(rquestURL);
// 通过正则表达式匹配,取出data-src的图片链接放入到list中
List<String> imageUrlList = getImageSrc(htmlContent);
for (String imageUrl : imageUrlList) {
try {
download(imageUrl, IMAGE_SAVE_PATH);
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
System.out.println("从{" + rquestURL + "]网站,共抓取[" + (imageIndex - 1) + "]张图片");
}
/**
* 解析图片url路径,保存到对应目录下
*
* @param imageUrl
* @param imageSavePath
* @throws IOException
*/
private static void download(String imageUrl, String imageSavePath) throws IOException {
String imageType = "";
boolean flag = false;
for (String suffix : IMAGE_TYPE_SUFFIX) {
if (imageUrl.lastIndexOf(suffix) > -1 || imageUrl.lastIndexOf(suffix.toUpperCase()) > -1) {
flag = true;
imageType = suffix.replace("=", ".");
break;
}
}
// 存在该图片类型
if (flag) {
String filename = String.valueOf(imageIndex) + imageType;
download(imageUrl, filename, imageSavePath);
imageIndex++;
}
}
private static void download(String imageUrl, String filename, String imageSavePath) throws IOException {
if (StringUtils.isEmpty(imageUrl) || StringUtils.isEmpty(filename) || StringUtils.isEmpty(imageSavePath)) {
throw new IllegalArgumentException("方法入参不能为空");
}
// 如果目录不存在,就新增一个
File dir = new File(imageSavePath);
if (!dir.exists() && dir.isDirectory()) {
dir.mkdir();
}
// 构造URL
URL url = new URL(imageUrl);
// 打开连接
URLConnection urlConn = url.openConnection();
// 设置请求超时为5s
urlConn.setConnectTimeout(5 * 1000);
// 输入流
InputStream is = urlConn.getInputStream();
// 创建缓冲区
byte[] bs = new byte[1024];
// 读取数据长度
int len;
// 输出的文件流
OutputStream os = new FileOutputStream(dir.getPath() + "/" + filename);
while ((len = is.read(bs)) != -1) {
os.write(bs, 0, len);
}
// 资源释放
os.close();
is.close();
}
/**
* 通过正则表达式的匹配,获取ImageSrc的地址
*
* @param htmlContent
* @return
*/
private static List<String> getImageSrc(String htmlContent) {
if (htmlContent == null) {
throw new IllegalArgumentException("html请求内容不能为空.");
}
List<String> listImageUrl = getImageUrl(htmlContent);
List<String> listImageSrc = new ArrayList<>();
for (String imageContent : listImageUrl) {
Matcher matcher = Pattern.compile(IMGSRC_REG).matcher(imageContent);
while (matcher.find()) {
listImageSrc.add(matcher.group().substring(0, matcher.group().length() - 1));
}
}
return listImageSrc;
}
/**
* 通过正则表达式获取ImageURL的地址
*
* @param htmlContent
* @return
*/
private static List<String> getImageUrl(String htmlContent) {
if (htmlContent == null) {
throw new IllegalArgumentException("html请求内容不能为空.");
}
List<String> listImgUrl = new ArrayList<String>();
Matcher matcher = Pattern.compile(IMGURL_REG).matcher(htmlContent);
while (matcher.find()) {
listImgUrl.add(matcher.group().replaceAll("'", ""));
}
return listImgUrl;
}
/**
* 读取url中的相应内容并返回
*
* @param requestUrl
* @return
*/
private static String ParserContext(String requestUrl) {
if (requestUrl == null) {
throw new IllegalArgumentException("url不能为空.");
}
String html = null;
// 创建httpClient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
try {
// 创建httpget对象
HttpGet httpGet = new HttpGet(requestUrl);
// 执行get请求
CloseableHttpResponse response = httpclient.execute(httpGet);
try {
// 获取响应实体
HttpEntity entity = response.getEntity();
if (entity != null) {
html = EntityUtils.toString(entity);
}
} finally {
response.close();
}
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭连接
try {
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return html;
}
}