java 爬取图片_Java爬取简单的网页内容和图片

本文介绍了使用Java进行简单网页内容和图片爬取的基本流程,包括匹配HTML内容、下载图片以及多线程爬取。在实践中,文章提到遇到的问题,如HTML内容缺失、正则表达式匹配不足、图片URL格式不规范等,并提到程序仅触及爬虫的基础应用,对于更复杂场景仍需深入学习和改进。
摘要由CSDN通过智能技术生成

Java爬取简单的网页内容和图片

根据java网络编程相关的内容,使用jdk提供的相关类可以得到url对应网页的html页面代码。

针对得到的html代码,通过使用正则表达式即可得到我们想要的内容。

比如,我们如果想得到一个网页上所有包括“java”关键字的文本内容,就可以逐行对网页代码进行正则表达式的匹配。最后达到去除html标签和不相关的内容,只得到包括“java”这个关键字的内容的效果。

从网页上爬取图片的流程和爬取内容的流程基本相同,但是爬取图片的步骤会多一步。

需要先用img标签的正则表达式匹配获取到img标签,再用src属性的正则表达式获取这个img标签中的src属性的图片url,然后再通过缓冲输入流对象读取到这个图片url的图片信息,配合文件输出流将读到的图片信息写入到本地即可。

爬虫除这两种玩法外,还有着许多的应用,比如还可以爬取一个网页上所有的邮箱、电话号码等等。

运行效果:

这些内容是我从csdn首页中根据“你”这一个关键字得到的。

这些是我从一些网站得到的图片

问题:

在看似没有问题的爬取代码背后其实还是存在着许多问题的,该程序只是对爬虫最初级的应用。比如我发现部分内容的html在浏览器的“检查”功能中明明存在,但是在网页源代码中就没有了相关的内容。还有文本匹配的正则表达式部分也存在问题。

在img src属性中,有部分图片的url是不带协议的(如:https://),还有部分图片的url是不带图片后缀(jpg、png、gif...)的。前者导致程序无法解析这个url,后者导致无法给下载的图片统一采用原命名。

有时匹配到的img src值还会出现非图片url的情况。还有时从页面上获取到的内容是unicode编码值。以及部分网站做了反爬虫处理等...

以上问题因为我对java知识、web知识、网络知识还有正则的知识了解的很少,所以我目前都无法解决。

这些问题就导致最后真正从网页上爬下来的内容,只是原网页很少的一部分。

我相信在以后这些问题都是会被逐个解决的。

另外我在程序中使用了多线程的功能,以达到可以在多个网页“同时”爬取的效果。

下面给出该程序的源代码。

编译环境:

windows jdk 9 idea

代码:

//Main.java 主类

package pers.baijiaming.download.main;

//主类public class Main

{

public static void main(String[] args)

{

createImageDownloadThread ("https://www.bilibili.com/", "downloadImg/b站/");

createImageDownloadThread("https://cn.bing.com/images/search?q=%E7%A6%8F%E5%88%A9&qs=n&form=QBIR&sp=-1&pq=%E7%A6%8F%E5%88%A9&sc=3-2&cvid=2AF12F93CAB34E8FBF902905B185583C&first=1&scenario=ImageBasicHover", "downloadImg/福利/");

createTextDownloadThread("https://www.csdn.net/", "你", "Text/", "testText.txt");

}

//创建并执行线程,获取图片 private static void createImageDownloadThread(String url, String path)

{

new Thread(new DownloadPictures(url, path)).start();

}

//获取文本内容 private static void createTextDownloadThread(String urlStr, String findText, String downloadPath, String fileName)

{

new Thread(new GetText(urlStr, findText, downloadPath, fileName)).start();

}

}

//DownloadPictures.java 爬取图片类

package pers.baijiaming.download.main;

import java.io.*; //io包import java.util.regex.*; //正则包import java.net.*; //网络包

/** 下载图片类* */

public final class DownloadPictures implements Runnable

{

private URL url = null; //URL private URLConnection urlConn = null; //url连接 private BufferedReader bufIn = null; //缓冲读取器,读取网页信息

private static final String IMG_REG = "]*?>"; //img标签正则 private static final String IMG_SRC_REG = "src\\s*=\\s*\"?(.*?)(\"|>|\\s+)"; //img src属性正则

private String downloadPath = null; //保存路径

//构造,参数:想要下载图片的网址、下载到的图片存放的文件路径 public DownloadPictures(String urlStr, String downloadPath)

{

createFolder(downloadPath); //创建文件夹

try {

url = new URL(urlStr);

urlConn = url.openConnection();

//设置请求属性,有部分网站不加这句话会抛出IOException: Server returned HTTP response code: 403 for URL异常 //如:b站 urlConn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

bufIn = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));

}

catch (Exception e) {

e.printStackTrace();

}

this.downloadPath = downloadPath;

}

//检测路径是否存在,不存在则创建 private void createFolder(String path)

{

File myPath = new File(path);

if (!myPath.exists()) //不存在则创建文件夹 myPath.mkdirs();

}

//下载函数 public void Download()

{

final int N = 20; //每一次处理的文本行数,这个数越小越容易遗漏图片链接,越大效率越低 (理论上)

String line = "";

String text = "";

while (line != null) //网页内容被读完时结束循环 {

for(int i = 0; i < N; i++) //读取N行网页信息存入到text当中,因为src内容可能分为多行,所以使用这种方法 try {

line = bufIn.readLine(); //从网页信息中获取一行文本

if(line != null) //判断防止把null也累加到text中 text += line;

}

catch (IOException e) {

e.printStackTrace();

}

//将img标签正则封装对象再调用matcher方法获取一个Matcher对象 final Matcher imgM = Pattern.compile(IMG_REG).matcher(text);

if(!imgM.find()) //如果在当前text中没有找到img标签则结束本次循环 continue;

//将img src正则封装对象再调用matcher方法获取一个Matcher对象 //用于匹配的文本为找到的整个img标签 final Matcher imgSrcM = Pattern.compile(IMG_SRC_REG).matcher(imgM.group());

while (imgSrcM.find()) //从img标签中查找src内容 {

String imageLink = imgSrcM.group(1); //从正则中的第一个组中得到图片链接

print(imageLink); //打印一遍链接

//如果得到的src内容没有写协议,则添加上// if(!imageLink.matches("https://[\\s\\S]*")) //这里有问题// imageLink = "https://" + imageLink;

print(imageLink); //打印一遍链接

try

{

//缓冲输入流对象,用于读取图片链接的图片数据 //在链接的图片不存在时会抛出未找到文件异常 final BufferedInputStream in = new BufferedInputStream(new URL(imageLink).openStream());

//文件输出流对象用于将从url中读取到的图片数据写入到本地 //保存的路径为downloadPath,保存的图片名为时间戳+".png" final FileOutputStream file = new FileOutputStream(new File(downloadPath + System.currentTimeMillis() + ".png"));

int temp; //用于保存in从图片连接中获取到的数据 while ((temp = in.read()) != -1)

file.write(temp); //将数据写入到本地路径中

//关闭流 file.close();

in.close();

//下载完一张图片后休息一会 try {

Thread.sleep(800);

}

catch (InterruptedException e) {

e.printStackTrace();

}

}

catch (Exception e)

{

e.printStackTrace();

}

}

//将text中的文本清空 text = "";

}

}

//run @Override

public void run()

{

Download(); //下载函数 }

//打印语句 public void print(Object obj)

{

System.out.println(obj);

}

}

//GetTest.java爬取文本内容类

package pers.baijiaming.download.main;

import java.io.*;

import java.net.URL;

import java.net.URLConnection;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

public final class GetText implements Runnable

{

private URL url = null; //URL private URLConnection urlConn = null; //url连接 private BufferedReader bufIn = null; //缓冲读取器,读取网页信息

// private static final String TEXT_REG = "([[[^\\x00-\\xff]|\\w]&&[^u003E]])+"; //文本内容正则 private static final String TEXT_REG = "[[\\s\\S]&&[^<>\\n ]]*"; //文本内容正则,这里有些问题,试了很久,无法排除一个空格的情况// ([\s\S]*?)[a-zA-Z]*?>

private String findText = null; //要查找的内容

private String downloadPath = null; //保存路径 private String fileName = null; //文件名

//构造,参数:url、要查找的文本、保存路径,文件名 public GetText(String urlStr, String findText, String downloadPath, String fileName)

{

createFolder(downloadPath); //创建文件夹

try {

url = new URL(urlStr);

urlConn = url.openConnection();

//设置请求属性,有部分网站不加这句话会抛出IOException: Server returned HTTP response code: 403 for URL异常 //如:b站 urlConn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

bufIn = new BufferedReader(new InputStreamReader(urlConn.getInputStream()));

}

catch (Exception e) {

e.printStackTrace();

}

this.downloadPath = downloadPath;

this.fileName = fileName;

this.findText = findText;

}

//检测路径是否存在,不存在则创建 private void createFolder(String path)

{

File myPath = new File(path);

if (!myPath.exists()) //不存在则创建文件夹 myPath.mkdirs();

}

//下载函数 private void Download()

{

final int N = 10;

String line = "";

String textStr = "";

while (line != null)

{

for(int i = 0; i < N; i++) //将N行内容追加到textStr字符串中 try {

line = bufIn.readLine();

if(line != null)

textStr += line;

}

catch (IOException e) {

e.printStackTrace();

}

try

{

//将img标签正则封装对象再调用matcher方法获取一个Matcher对象 final Matcher textMatcher = Pattern.compile(TEXT_REG + findText + TEXT_REG).matcher(textStr);

final FileWriter fw = new FileWriter(downloadPath + fileName, true); //文件编写,续写文件

while (textMatcher.find()) //查找匹配文本 {

fw.write(textMatcher.group() + "\n"); //写入到文件中 print(textMatcher.group()); //打印一遍 }

// print(textStr); fw.close();

textStr = "";

}

catch (Exception e)

{

e.printStackTrace();

}

}

}

//run @Override

public void run()

{

Download();

}

//打印语句 private void print(Object obj)

{

System.out.println(obj);

}

}

----

程序中还存在着许多问题,还请多多包涵。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值