前端時間公司項目需要抓取各類數據,py玩的不6,只好研究Java爬蟲方案,做一個總結。
開發環境:
springBoot 2.2.6、jdk1.8。
1、導入依賴
us.codecraftwebmagic-core0.7.3 --> --> org.slf4j--> slf4j-log4j12--> --> -->us.codecraftwebmagic-extension0.7.3com.google.guavaguava16.0
話不多說,直接上代碼。
基礎案例
下面代碼說明以一個類似列表的頁面為例
package com.crawler.project.proTask; import com.alibaba.fastjson.JSONObject; import org.springframework.scheduling.annotation.Scheduled; import us.codecraft.webmagic.Page; import us.codecraft.webmagic.Site; import us.codecraft.webmagic.Spider; import us.codecraft.webmagic.processor.PageProcessor; import us.codecraft.webmagic.scheduler.BloomFilterDuplicateRemover; import us.codecraft.webmagic.scheduler.QueueScheduler; import us.codecraft.webmagic.selector.Selectable; import java.util.List; public class TaskProcessor implements PageProcessor { /* * 此方法為爬蟲業務實現 * */ @Override public void process(Page page) { //1、爬蟲任務獲取到一個page 解析page上的列表 Listlist = page.getHtml().css("css selector").nodes(); if (list.size() > 0){//說明為列表頁面、需要解析列表中每個元素的鏈接,存入待獲取page隊列中 for (Selectable selectable : list) { //遍歷集合,將每個元素鏈接存入待獲取page隊列中 page.addTargetRequest(selectable.links().toString()); } //同時將下一頁的url存入隊列中 page.addTargetRequest("下一頁的url"); }else { //此時為列表中單個元素對應的詳情頁 //在自定義方法中處理詳細頁,獲取需要的數據進行處理。 handle(page); } } private void handle(Page page) { //例如 處理後的數據為一個JSONObject對象 JSONObject tmp = new JSONObject(); //將這個tmp交由自定義的TaskPipline類處理,若未自定義Pipline並設置到Spider參數中,框架會默認將tmp打印到控制檯。 page.putField("obj",tmp); } /* * 此方法為配置爬蟲過程的一些參數 * */ private Site site = Site.me() .setCharset("UTF-8") .setTimeOut(60 * 1000) .setRetrySleepTime(60 * 1000) .setCycleRetryTimes(5); @Override public Site getSite() { return site; } /* 設置定時任務,執行爬蟲任務 * */ @Scheduled(initialDelay = 1 * 1000,fixedDelay = 2 * 1000) public void process(){ System.out.println("開始執行爬蟲抓取任務"); Spider.create(new TaskProcessor())//注意這裡的類名要和當前類名對應 .addUrl("起始頁url") .addPipeline(new TaskPipeline()) //此處課自定義 數據處理類 (在handle()方法中有); .setScheduler(new QueueScheduler().setDuplicateRemover(new BloomFilterDuplicateRemover(100000))) .thread(3)//此處設置線程數量(不宜過多,最好和列表頁中列表元素數量一致) .run(); } }
package com.crawler.project.proTask; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import us.codecraft.webmagic.ResultItems; import us.codecraft.webmagic.Task; import us.codecraft.webmagic.pipeline.Pipeline; public class TaskPipeline implements Pipeline { @Override public void process(ResultItems resultItems, Task task) { if (resultItems.getAll() .size() > 0){ Object obj = resultItems.getAll().get("obj"); JSONObject jsonObject = JSON.parseObject(obj.toString()); //獲取到JSONObject對象下面可進行自定義的業務處理。 } } }
特殊情況一
需根據鏈接下載圖片或文件
eg:在上面說到的詳情頁中含有iframe。
1、首先獲取iframe的src
//獲得iframe的src (這裡要注意獲得的src是絕對路徑還是相對路徑,相對路徑需要拼接主站點url) String src = html.css("css selector", "src").toString(); //採用jsoup解析 Document document = Jsoup.parse(new URL(src),1000); //獲得需要的元素 Element ele = document.select("css selector").last(); //獲取需要下載的文件的鏈接 String downUrl = ele.attr("href"); //根據鏈接下載文件 返回一個文件的名稱 String fileName = downloadFile(downUrl);
//通過url下載文件 public String downloadFile(String fileUrl) throws FileNotFoundException{ try{ URL httpUrl = new URL(fileUrl); String fileName = UUID.randomUUID().toString() + ".mp3"; File file = new File(this.STATIC_FILEPATH + fileName); System.out.println("============保存文件方法被調用==============="); FileUtils.copyURLToFile(httpUrl,file); return fileName; }catch (Exception e){ e.printStackTrace(); return null; } }
特殊情況二
有些https站點 無法直接使用WebMagic默認的下載器下載,此時我們可以根據站點ssl類型修改下載器。
在項目中創建一個包用於存放自定義(修改)的下載器類
(!!!摘自webMagic框架中HttpClientDownloader,基於此類修改!!!)
/* 此方法中需要傳入一個自定義的生成器(HttpClientGenerator) */ package com.crawler.project.spider_download; import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import us.codecraft.webmagic.Page; import us.codecraft.webmagic.Request; import us.codecraft.webmagic.Site; import us.codecraft.webmagic.Task; import us.codecraft.webmagic.downloader.AbstractDownloader; import us.codecraft.webmagic.downloader.HttpClientRequestContext; import us.codecraft.webmagic.downloader.HttpUriRequestConverter; import us.codecraft.webmagic.proxy.Proxy; import us.codecraft.webmagic.proxy.ProxyProvider; import us.codecraft.webmagic.selector.PlainText; import us.codecraft.webmagic.utils.CharsetUtils; import us.codecraft.webmagic.utils.HttpClientUtils; import java.io.IOException; import java.nio.charset.Charset; import java.util.HashMap; import java.util.Map; /** * The http downloader based on HttpClient. * * @author code4crafter@gmail.com * @since 0.1.0 */ public class HttpClientDownloader extends AbstractDownloader { private Logger logger = LoggerFactory.getLogger(getClass()); private final Map
然後在自定義的HttpClientGenerator類中修改有關ssl的參數
(!!!摘自webMagic框架中HttpClientGenerator,基於此類修改!!!)
/* 自定義的HttpClientGenerator生成器 */ package com.sealion_crawler.project.spider_download; import org.apache.http.HttpException; import org.apache.http.HttpRequest; import org.apache.http.HttpRequestInterceptor; import org.apache.http.client.CookieStore; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; import org.apache.http.config.SocketConfig; import org.apache.http.conn.socket.ConnectionSocketFactory; import org.apache.http.conn.socket.PlainConnectionSocketFactory; import org.apache.http.conn.ssl.DefaultHostnameVerifier; import org.apache.http.conn.ssl.SSLConnectionSocketFactory; import org.apache.http.impl.client.*; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.http.protocol.HttpContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import us.codecraft.webmagic.Site; import us.codecraft.webmagic.downloader.CustomRedirectStrategy; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import java.io.IOException; import java.security.KeyManagementException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Map; /** * @author code4crafter@gmail.com * @since 0.4.0 */ public class HttpClientGenerator { private transient Logger logger = LoggerFactory.getLogger(getClass()); private PoolingHttpClientConnectionManager connectionManager; public HttpClientGenerator() { Registry
好了,到這裡 基於WebMagic框架 實現爬蟲、包括jsoup的使用總結就到這裡的。
[zmcjlove ] springBoot+webMagic實現網站爬蟲的實例代碼已經有250次圍觀