jsoup爬取百度瀑布流图片

Java爬取百度图片
本文介绍了一种使用Java和Jsoup库爬取百度图片的方法,不仅能够抓取静态网页图片,还能通过发送Ajax请求获取动态加载的内容。文章提供了一个示例程序,能够根据指定的关键字和页数下载图片至本地。

       是的,Java也可以做网络爬虫,不仅可以爬静态网页的图片,也可以爬动态网页的图片,比如采用Ajax技术进行异步加载的百度瀑布流。

      以前有写过用Java进行百度图片的抓取,但只能抓取到第一二页,本博文则对此问题进行了深入研究,提出了另外一种思路解决问题。我的思路是这样的:以前人们总认为既然百度瀑布流是采用Javascript进行异步加载的,那么爬取图片至少要有一个模拟浏览器,比如Java领域中的无界面浏览器工具HtmlUnit,但后来我发现其实Jsoup也是可以的,只要用Jsoup去向百度服务器发送Ajax请求就行了,幸运的是我在观察百度图片的ajax请求时还真发现有两个类型的请求方式:avatarjson和acjson,实验告诉我们第一种请求方式已经几乎可以满足我们的所有需求。

      本博文所实现的效果是:根据输入的多个关键字,可以按定制的页数把各自关键字的搜索结果下载到本地文件夹中。具体如下所示:





废话不多说,程序满上------->

package com.kendy.spider;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringEscapeUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

// 爬取百度图片
public class JsoupBaidu2 {
	
	public static void main(String[] args) throws Exception{
		String downloadPath = "C:\\Users\\Kendy\\Desktop\\中国明星图";
		List<String> list = nameList("凯莉·布鲁克 詹妮弗·洛佩兹 碧昂斯·诺里斯");
		getPictures(list,1,downloadPath); //1代表下载一页,一页一般有30张图片
	}
	
    public static void getPictures(List<String> keywordList, int max,String downloadPath) throws Exception{ // key为关键词,max作为爬取的页数
        String gsm=Integer.toHexString(max)+"";
        String finalURL = "";
        String tempPath = "";
       for(String keyword : keywordList){
    	   tempPath = downloadPath;
           if(!tempPath.endsWith("\\")){
           	tempPath = downloadPath+"\\";
           }
           tempPath = tempPath+keyword+"\\";
    	   File f = new File(tempPath);
    	   if(!f.exists()){
    		   f.mkdirs();
    	   }
    	   int picCount = 1;
	       for(int page=0;page<=max;page++) { 
	    	   sop("正在下载第"+page+"页面");
	            Document document = null;
	            try {
	            	String url ="http://image.baidu.com/search/avatarjson?tn=resultjsonavatarnew&ie=utf-8&word="+keyword+"&cg=star&pn="+page*30+"&rn=30&itg=0&z=0&fr=&width=&height=&lm=-1&ic=0&s=0&st=-1&gsm="+Integer.toHexString(page*30);
	            	sop(url);
	            	document = Jsoup.connect(url).data("query", "Java")//请求参数  
							 .userAgent("Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)")//设置urer-agent  get();
							 .timeout(5000)
							 .get();
	                String xmlSource = document.toString();
	                xmlSource = StringEscapeUtils.unescapeHtml3(xmlSource);
	                sop(xmlSource);
	                String reg = "objURL\":\"http://.+?\\.jpg";
	        		Pattern pattern = Pattern.compile(reg);
	                Matcher m = pattern.matcher(xmlSource);
	                while (m.find()) {
	                	finalURL = m.group().substring(9);
	                	sop(keyword+picCount+++":"+finalURL);
	                	download(finalURL,tempPath);
	                	sop("             下载成功");
	                } 
	            } catch (IOException e) {
	                e.printStackTrace();
	            }
	        }
       }
       sop("下载完毕");
       delMultyFile(downloadPath);
       sop("已经删除所有空图");
    }
    public static void delMultyFile(String path){
		File file = new File(path);
		if(!file.exists())
			throw new RuntimeException("File \""+path+"\" NotFound when excute the method of delMultyFile()....");
		File[] fileList = file.listFiles();
		File tempFile=null;
		for(File f : fileList){
			if(f.isDirectory()){
				delMultyFile(f.getAbsolutePath());
			}else{
				if(f.length()==0)
					sop(f.delete()+"---"+f.getName());
			}
		}
	}
    public static List<String> nameList(String nameList){
    	List<String> arr = new ArrayList<>();
    	String[] list;
    	if(nameList.contains(","))
    		list= nameList.split(",");
    	else if(nameList.contains("、"))
    		list= nameList.split("、");
    	else if(nameList.contains(" "))
    		list= nameList.split(" ");
    	else{
    		arr.add(nameList);
    		return arr;
    	}
    	for(String s : list){
    		arr.add(s);
    	}
    	return arr;
    }
    public static void sop(Object obj){
    	System.out.println(obj);
    }
  //根据图片网络地址下载图片
  	public static void download(String url,String path){
  		//path = path.substring(0,path.length()-2);
  		File file= null;
  		File dirFile=null;
  		FileOutputStream fos=null;
  		HttpURLConnection httpCon = null;
  		URLConnection  con = null;
  		URL urlObj=null;
  		InputStream in =null;
  		byte[] size = new byte[1024];
  		int num=0;
  		try {
  			String downloadName= url.substring(url.lastIndexOf("/")+1);
  			dirFile = new File(path);
  			if(!dirFile.exists() && path.length()>0){
  				if(dirFile.mkdir()){
  					sop("creat document file \""+path.substring(0,path.length()-1)+"\" success...\n");
  				}
  			}else{
  				file = new File(path+downloadName);
  				fos = new FileOutputStream(file);
  				if(url.startsWith("http")){
  					urlObj = new URL(url);
  					con = urlObj.openConnection();
  					httpCon =(HttpURLConnection) con;
  					in = httpCon.getInputStream();
  					while((num=in.read(size)) != -1){
  						for(int i=0;i<num;i++)
  						   fos.write(size[i]);
  					}
  				}
  			}
  		}catch (FileNotFoundException notFoundE) {
  			sop("找不到该网络图片....");
  		}catch(NullPointerException nullPointerE){
  			sop("找不到该网络图片....");
  		}catch(IOException ioE){
  			sop("产生IO异常.....");
  		}catch (Exception e) {
  			e.printStackTrace();
  		}finally{
  			try {
  				fos.close();
  			} catch (Exception e) {
  				e.printStackTrace();
  			}
  		}
  	}
}


### 爬取百度图片的解决方案及代码示例 使用 JavaJsoup 庉库爬取百度图片需要理解网页结构和动态加载机制。以下是实现此功能的详细方法和代码示例。 #### 1. 确定目标网页 百度图片搜索页面是通过 AJAX 动态加载的,因此直接解析 HTML 可能无法获取到完整的图片信息。通常需要结合工具如 PhantomJS 或 Selenium 模拟浏览器行为[^1]。然而,对于简单的静态内容,Jsoup 仍然可以处理。 #### 2. 获取网页内容 使用 Jsoup 的 `connect(String url)` 方法连接目标 URL,并通过 `get()` 方法获取网页内容。需要注意的是,如果目标页面包含动态加载的内容,可能需要额外的工具来模拟浏览器行为[^2]。 ```java import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; public class BaiduImageCrawler { public static void main(String[] args) { String baiduImageUrl = "https://image.baidu.com/search/index?tn=baiduimage&word=关键词"; try { // 连接并获取网页内容 Document document = Jsoup.connect(baiduImageUrl).userAgent("Mozilla/5.0").get(); // 解析图片元素 Elements imgElements = document.select("img"); // 输出图片链接 for (Element img : imgElements) { String imageUrl = img.attr("data-src"); // 注意:百度图片可能使用 data-src 属性存储实际链接 if (!imageUrl.isEmpty()) { System.out.println(imageUrl); } } } catch (Exception e) { e.printStackTrace(); } } } ``` #### 3. 处理动态加载内容 如果百度图片的某些部分是通过 AJAX 动态加载的,则需要使用其他工具(如 Selenium 或 PhantomJS)来模拟浏览器行为。以下是一个结合 Selenium 的简单示例: ```java import org.openqa.selenium.WebDriver; import org.openqa.selenium.chrome.ChromeDriver; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; public class BaiduImageDynamicCrawler { public static void main(String[] args) { // 设置 ChromeDriver 路径 System.setProperty("webdriver.chrome.driver", "path/to/chromedriver"); // 初始化 WebDriver WebDriver driver = new ChromeDriver(); String baiduImageUrl = "https://image.baidu.com/search/index?tn=baiduimage&word=关键词"; try { // 打开目标页面 driver.get(baiduImageUrl); // 获取页面源码 String pageSource = driver.getPageSource(); Document document = Jsoup.parse(pageSource); // 解析图片元素 Elements imgElements = document.select("img"); for (Element img : imgElements) { String imageUrl = img.attr("data-src"); if (!imageUrl.isEmpty()) { System.out.println(imageUrl); } } } catch (Exception e) { e.printStackTrace(); } finally { // 关闭浏览器 driver.quit(); } } } ``` #### 4. 存储图片数据 如果需要将图片链接保存到数据库中,可以参考 MySQL 数据库的存储方式[^3]。以下是一个简单的存储示例: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; public class ImageStorage { public static void saveImageToDatabase(String imageUrl) { String jdbcUrl = "jdbc:mysql://localhost:3306/your_database"; String username = "root"; String password = "password"; try (Connection connection = DriverManager.getConnection(jdbcUrl, username, password)) { String sql = "INSERT INTO images (url) VALUES (?)"; try (PreparedStatement statement = connection.prepareStatement(sql)) { statement.setString(1, imageUrl); statement.executeUpdate(); } } catch (Exception e) { e.printStackTrace(); } } } ``` #### 注意事项 - 百度图片页面可能会频繁更新其 HTML 结构,因此需要定期检查选择器是否仍然有效。 - 遵守目标网站的 robots.txt 文件和相关法律条款,避免违反爬虫协议。
评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值