Jsoup簡單例子2.0——多執行緒爬取網頁內的郵箱
阿新 • • 發佈:2018-11-10
上一篇文章講了利用Jsoup爬取貼吧帖子裡的郵箱,雖然爬取成功了,但我對效率有所追求。10頁的帖子爬取了兩百多個郵箱,最快用時8秒,一般需要9秒。在思考了一下怎麼提升效率後,決定採用多執行緒的方式爬取網頁內的郵箱。廢話不多說,直接上程式碼。
引入Jsoup的jar包此處省略,沒有的可以檢視上篇文章。
import java.io.IOException; import java.util.HashSet; import java.util.Queue; import java.util.Set; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.atomic.AtomicInteger; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; /** * 多執行緒爬取郵箱 * @author pactera * */ public class JsoupTest4 { /** * Queue:先入先出(FIFO)的資料結構 * LinkedBlockingQueue:一個由連結節點支援的可選有界佇列 */ //等待爬取的url private static volatile Queue<String> queue = new LinkedBlockingQueue<String>(); //爬取過的url private static volatile Set<String> allOverUrl=new HashSet<>(); //匯流排程5條 private static int MAX_THREAD=5; //開始時間 private static long startTime=0; //記錄獲取的郵箱個數 private static int emailCount=0; //爬取帖子的頁數(10頁) private static AtomicInteger pageCount=new AtomicInteger(10); public static void main(String[] args) { for(int i =1;i <= pageCount.get();i++) { String url = "https://tieba.baidu.com/p/3349997454?pn="+i; //將獲取的url放入等待佇列中 queue.add(url); } //記錄開始時間 startTime = System.currentTimeMillis(); for(int i = 0;i < MAX_THREAD;i++) { new JsoupTest4().new MyThread().start(); } } /** * 網頁資料爬取 */ public static void work() { String url = queue.poll(); //檢測執行緒是否執行 System.out.println("當前執行:"+Thread.currentThread().getName()+" 爬取執行緒處理爬取:"+url); try { Document document = Jsoup.connect(url) //偽裝成瀏覽器進行抓取 .header("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20100101 Firefox/33.0") .get(); Element main = document.getElementById("j_p_postlist"); Elements content = main.select("div.l_post_bright") .select("div.d_post_content_main") .select("div.p_content") .select("cc") .select("div.d_post_content"); //遍歷每一帖的內容 for (Element element : content) { String Content = element.text(); //正則表示式判斷郵箱 String patternStr = "[\\w[.-]]
[email protected][\\w[.-]]+\\.[\\w]+"; Pattern pattern = Pattern.compile(patternStr); Matcher matcher = pattern.matcher(Content); //如果含有郵箱,獲取到的郵箱個數emailCount+1,並輸出 if(matcher.find()) { emailCount++; //輸出郵箱 //System.out.println(matcher.group()); } } } catch (IOException e) { e.printStackTrace(); } //將當前url歸列到alloverurl中 allOverUrl.add(url); System.out.println(url+"網頁爬取完成,已爬取數量:"+allOverUrl.size()); //繼續爬取其他連結 if(allOverUrl.size() == pageCount.get()) { long endTime = System.currentTimeMillis(); System.out.println("爬取結束,耗時:"+(endTime - startTime)/1000+"s"); System.out.println("獲取了"+emailCount+"個郵箱"); } } /** * 執行緒分配任務 * @author pactera * */ public class MyThread extends Thread{ @Override public void run() { do{ work(); }while(queue.size() > 0); } } }
最後比較一下效率,先看單執行緒的用時:
多執行緒用時:
開啟了5個執行緒,效率提升了5倍,厲害厲害。