循环爬取图片_Java爬取简单的网页内容和图片
Java爬取簡(jiǎn)單的網(wǎng)頁內(nèi)容和圖片
根據(jù)java網(wǎng)絡(luò)編程相關(guān)的內(nèi)容,使用jdk提供的相關(guān)類可以得到url對(duì)應(yīng)網(wǎng)頁的html頁面代碼。
針對(duì)得到的html代碼,通過使用正則表達(dá)式即可得到我們想要的內(nèi)容。
比如,我們?nèi)绻氲玫揭粋€(gè)網(wǎng)頁上所有包括“java”關(guān)鍵字的文本內(nèi)容,就可以逐行對(duì)網(wǎng)頁代碼進(jìn)行正則表達(dá)式的匹配。最后達(dá)到去除html標(biāo)簽和不相關(guān)的內(nèi)容,只得到包括“java”這個(gè)關(guān)鍵字的內(nèi)容的效果。
從網(wǎng)頁上爬取圖片的流程和爬取內(nèi)容的流程基本相同,但是爬取圖片的步驟會(huì)多一步。
需要先用img標(biāo)簽的正則表達(dá)式匹配獲取到img標(biāo)簽,再用src屬性的正則表達(dá)式獲取這個(gè)img標(biāo)簽中的src屬性的圖片url,然后再通過緩沖輸入流對(duì)象讀取到這個(gè)圖片url的圖片信息,配合文件輸出流將讀到的圖片信息寫入到本地即可。
爬蟲除這兩種玩法外,還有著許多的應(yīng)用,比如還可以爬取一個(gè)網(wǎng)頁上所有的郵箱、電話號(hào)碼等等。
運(yùn)行效果:
這些內(nèi)容是我從csdn首頁中根據(jù)“你”這一個(gè)關(guān)鍵字得到的。
這些是我從一些網(wǎng)站得到的圖片
問題:
在看似沒有問題的爬取代碼背后其實(shí)還是存在著許多問題的,該程序只是對(duì)爬蟲最初級(jí)的應(yīng)用。比如我發(fā)現(xiàn)部分內(nèi)容的html在瀏覽器的“檢查”功能中明明存在,但是在網(wǎng)頁源代碼中就沒有了相關(guān)的內(nèi)容。還有文本匹配的正則表達(dá)式部分也存在問題。
在img src屬性中,有部分圖片的url是不帶協(xié)議的(如:https://),還有部分圖片的url是不帶圖片后綴(jpg、png、gif...)的。前者導(dǎo)致程序無法解析這個(gè)url,后者導(dǎo)致無法給下載的圖片統(tǒng)一采用原命名。
有時(shí)匹配到的img src值還會(huì)出現(xiàn)非圖片url的情況。還有時(shí)從頁面上獲取到的內(nèi)容是unicode編碼值。以及部分網(wǎng)站做了反爬蟲處理等...
以上問題因?yàn)槲覍?duì)java知識(shí)、web知識(shí)、網(wǎng)絡(luò)知識(shí)還有正則的知識(shí)了解的很少,所以我目前都無法解決。
這些問題就導(dǎo)致最后真正從網(wǎng)頁上爬下來的內(nèi)容,只是原網(wǎng)頁很少的一部分。
我相信在以后這些問題都是會(huì)被逐個(gè)解決的。
另外我在程序中使用了多線程的功能,以達(dá)到可以在多個(gè)網(wǎng)頁“同時(shí)”爬取的效果。
下面給出該程序的源代碼。
編譯環(huán)境:
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");}//創(chuàng)建并執(zhí)行線程,獲取圖片private static void createImageDownloadThread(String url, String path){new Thread(new DownloadPictures(url, path)).start();}//獲取文本內(nèi)容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.*; //網(wǎng)絡(luò)包/*
* 下載圖片類
* */
public final class DownloadPictures implements Runnable
{private URL url = null; //URLprivate URLConnection urlConn = null; //url連接private BufferedReader bufIn = null; //緩沖讀取器,讀取網(wǎng)頁信息private static final String IMG_REG = "<img.*srcs*=s*(.*?)[^>]*?>"; //img標(biāo)簽正則private static final String IMG_SRC_REG = "srcs*=s*"?(.*?)("|>|s+)"; //img src屬性正則private String downloadPath = null; //保存路徑//構(gòu)造,參數(shù):想要下載圖片的網(wǎng)址、下載到的圖片存放的文件路徑public DownloadPictures(String urlStr, String downloadPath){createFolder(downloadPath); //創(chuàng)建文件夾try {url = new URL(urlStr);urlConn = url.openConnection();//設(shè)置請(qǐng)求屬性,有部分網(wǎng)站不加這句話會(huì)拋出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;}//檢測(cè)路徑是否存在,不存在則創(chuàng)建private void createFolder(String path){File myPath = new File(path);if (!myPath.exists()) //不存在則創(chuàng)建文件夾myPath.mkdirs();}//下載函數(shù)public void Download(){final int N = 20; //每一次處理的文本行數(shù),這個(gè)數(shù)越小越容易遺漏圖片鏈接,越大效率越低 (理論上)String line = "";String text = "";while (line != null) //網(wǎng)頁內(nèi)容被讀完時(shí)結(jié)束循環(huán){for(int i = 0; i < N; i++) //讀取N行網(wǎng)頁信息存入到text當(dāng)中,因?yàn)閟rc內(nèi)容可能分為多行,所以使用這種方法try {line = bufIn.readLine(); //從網(wǎng)頁信息中獲取一行文本if(line != null) //判斷防止把null也累加到text中text += line;}catch (IOException e) {e.printStackTrace();}//將img標(biāo)簽正則封裝對(duì)象再調(diào)用matcher方法獲取一個(gè)Matcher對(duì)象final Matcher imgM = Pattern.compile(IMG_REG).matcher(text);if(!imgM.find()) //如果在當(dāng)前text中沒有找到img標(biāo)簽則結(jié)束本次循環(huán)continue;//將img src正則封裝對(duì)象再調(diào)用matcher方法獲取一個(gè)Matcher對(duì)象//用于匹配的文本為找到的整個(gè)img標(biāo)簽final Matcher imgSrcM = Pattern.compile(IMG_SRC_REG).matcher(imgM.group());while (imgSrcM.find()) //從img標(biāo)簽中查找src內(nèi)容{String imageLink = imgSrcM.group(1); //從正則中的第一個(gè)組中得到圖片鏈接print(imageLink); //打印一遍鏈接//如果得到的src內(nèi)容沒有寫協(xié)議,則添加上
// if(!imageLink.matches("https://[sS]*")) //這里有問題
// imageLink = "https://" + imageLink;print(imageLink); //打印一遍鏈接try{//緩沖輸入流對(duì)象,用于讀取圖片鏈接的圖片數(shù)據(jù)//在鏈接的圖片不存在時(shí)會(huì)拋出未找到文件異常final BufferedInputStream in = new BufferedInputStream(new URL(imageLink).openStream());//文件輸出流對(duì)象用于將從url中讀取到的圖片數(shù)據(jù)寫入到本地//保存的路徑為downloadPath,保存的圖片名為時(shí)間戳+".png"final FileOutputStream file = new FileOutputStream(new File(downloadPath + System.currentTimeMillis() + ".png"));int temp; //用于保存in從圖片連接中獲取到的數(shù)據(jù)while ((temp = in.read()) != -1)file.write(temp); //將數(shù)據(jù)寫入到本地路徑中//關(guān)閉流file.close();in.close();//下載完一張圖片后休息一會(huì)try {Thread.sleep(800);}catch (InterruptedException e) {e.printStackTrace();}}catch (Exception e){e.printStackTrace();}}//將text中的文本清空text = "";}}//run@Overridepublic void run(){Download(); //下載函數(shù)}//打印語句public void print(Object obj){System.out.println(obj);}
}//GetTest.java 爬取文本內(nèi)容類
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; //URLprivate URLConnection urlConn = null; //url連接private BufferedReader bufIn = null; //緩沖讀取器,讀取網(wǎng)頁信息// private static final String TEXT_REG = "([[[^x00-xff]|w]&&[^u003E]])+"; //文本內(nèi)容正則private static final String TEXT_REG = "[[sS]&&[^<>n ]]*"; //文本內(nèi)容正則,這里有些問題,試了很久,無法排除一個(gè)空格的情況
// <[a-zA-Z]+.*?>([sS]*?)</[a-zA-Z]*?>private String findText = null; //要查找的內(nèi)容private String downloadPath = null; //保存路徑private String fileName = null; //文件名//構(gòu)造,參數(shù):url、要查找的文本、保存路徑,文件名public GetText(String urlStr, String findText, String downloadPath, String fileName){createFolder(downloadPath); //創(chuàng)建文件夾try {url = new URL(urlStr);urlConn = url.openConnection();//設(shè)置請(qǐng)求屬性,有部分網(wǎng)站不加這句話會(huì)拋出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;}//檢測(cè)路徑是否存在,不存在則創(chuàng)建private void createFolder(String path){File myPath = new File(path);if (!myPath.exists()) //不存在則創(chuàng)建文件夾myPath.mkdirs();}//下載函數(shù)private void Download(){final int N = 10;String line = "";String textStr = "";while (line != null){for(int i = 0; i < N; i++) //將N行內(nèi)容追加到textStr字符串中try {line = bufIn.readLine();if(line != null)textStr += line;}catch (IOException e) {e.printStackTrace();}try{//將img標(biāo)簽正則封裝對(duì)象再調(diào)用matcher方法獲取一個(gè)Matcher對(duì)象final Matcher textMatcher = Pattern.compile(TEXT_REG + findText + TEXT_REG).matcher(textStr);final FileWriter fw = new FileWriter(downloadPath + fileName, true); //文件編寫,續(xù)寫文件while (textMatcher.find()) //查找匹配文本{fw.write(textMatcher.group() + "n"); //寫入到文件中print(textMatcher.group()); //打印一遍}// print(textStr);fw.close();textStr = "";}catch (Exception e){e.printStackTrace();}}}//run@Overridepublic void run(){Download();}//打印語句private void print(Object obj){System.out.println(obj);}
}----
程序中還存在著許多問題,還請(qǐng)多多包涵。
總結(jié)
以上是生活随笔為你收集整理的循环爬取图片_Java爬取简单的网页内容和图片的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 我是年费怎么弄那个盘古坐骑
- 下一篇: 隔年增长的题_行测资料分析:一起聊聊隔年