http編程系列(二)——java爬蟲實現刷個人部落格的訪問量

  • 2019 年 10 月 30 日
  • 筆記

版權聲明:本文為部落客原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。

本文鏈接:https://blog.csdn.net/luo4105/article/details/72582692

實現功能

這裡實現的功能是一個根據個人部落格主頁,搜索出所有的個人博文鏈接,然後一個一個去訪問,從而增加訪問量。這裡我發現一個問題,csdn既沒有做介面ip訪問量的限制,訪問量統計時也沒有做同一ip相同時間段的重複訪問重複計數的處理。這也時這個程式能夠刷訪問量的原因。

思路

進入個人部落格主頁,如我的部落格:」http://blog.csdn.net/luo4105」,它會出來一個部落格的列表(blogListPage),但是,它沒有顯示所有的部落格,而是分頁顯示,這裡我們就找到下一頁

的鏈接並訪問它,然後如此遞歸,直到尾頁為止。這樣我們就獲得了所有的分頁部落格的地址。然後訪問所有的分頁部落格,拿到它們的頁面數據,找出所有的部落格鏈接,訪問。

這裡工作就分為以下幾步

1.根據個人主頁url,訪問個人主頁並拿到頁面數據

2.找出下一頁的URL並訪問,重複該動作直到沒有下一頁,將每個url都存到set集合中

3.遍歷set集合,訪問所有的部落格列表頁面,獲得頁面數據,找到頁面數據中所有的部落格鏈接,存入部落格鏈接的set集合

4.遍歷部落格鏈接的set集合,訪問所有部落格鏈接

具體實現步驟

1.根據個人主頁url,訪問個人主頁並拿到頁面數據

訪問url,並拿到響應的程式碼如下,為了重複使用,我將其放入工具類中。

訪問URL並拿到響應程式碼

public class HttpUtil {      public static InputStream doGet(String urlstr) throws IOException {         URL url= new URL(urlstr);         HttpURLConnection conn= (HttpURLConnection) url.openConnection();         conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");         InputStream inputStream= conn.getInputStream();         return inputStream;      }  }

將響應的InputStream轉成String的程式碼

public class StreamUtil {      public static String inputStreamToString(InputStream is, String charset) throws IOException {         byte[] bytes = new byte[1024];         int byteLength = 0;         StringBuffer sb = new StringBuffer();         while((byteLength = is.read(bytes)) != -1) {             sb.append(new String(bytes, 0, byteLength, charset));         }         return sb.toString();      }  }

綜合使用就是

public void addBlogListPageUrl(String pageUrl, Set<String> pagelistUrls) throws IOException {  	InputStream is = HttpUtil.doGet(pageUrl);  	String pageStr = StreamUtil.inputStreamToString(is, "UTF-8");  	is.close();  	System.out.println(pageStr);  }

這裡後台輸出頁面的程式碼。

2.找出下一頁的URL並訪問,重複該動作直到沒有下一頁,將每個url都存到set集合中

開啟f12,我們來看下一頁是怎麼樣的。

這裡我們可以通過下面的正則匹配<a href=」xxxxxx」>下一頁</a>標籤

private String nextPagePanner = "<a href="/luo4105/article/list/[0-9]{1,10}">下一頁</a>";	//下一頁的正則表達式

然後我們用正則匹配URL鏈接

private String nextPageUrlPanner = "/luo4105/article/list/[0-9]{1,10}";	//下一頁Url的正則表達式

加上匹配正則,功能程式碼如下

private String csdnBlogUrl = "http://blog.csdn.net/";  private String nextPagePanner = "<a href="/luo4105/article/list/[0-9]{1,10}">下一頁</a>";	//下一頁的正則表達式  	private String nextPageUrlPanner = "/luo4105/article/list/[0-9]{1,10}";						//下一頁Url的正則表達式  /**   * 通過下一頁,遍歷所有部落格目錄頁面鏈接   * @param pageUrl   * @param pagelistUrls   * @throws IOException   */  public void addBlogListPageUrl(String pageUrl, Set<String> pagelistUrls) throws IOException {  	InputStream is = HttpUtil.doGet(pageUrl);  	String pageStr = StreamUtil.inputStreamToString(is, "UTF-8");  	is.close();  	Pattern nextPagePattern = Pattern.compile(nextPagePanner);  	Matcher nextPagematcher = nextPagePattern.matcher(pageStr);  	if (nextPagematcher.find()) {  		nextPagePattern = Pattern.compile(nextPageUrlPanner);  		nextPagematcher = nextPagePattern.matcher(nextPagematcher.group(0));  		if (nextPagematcher.find()) {  			pagelistUrls.add(csdnBlogUrl + nextPagematcher.group(0));  			System.out.println("成功添加部落格列表頁面地址:" + csdnBlogUrl + nextPagematcher.group(0));  			//addBlogListPageUrl(csdnBlogUrl + nextPagematcher.group(0), pagelistUrls);這是調用添加blog鏈接的方法  		}  	}  }

3.遍歷set集合,訪問所有的部落格列表頁面,獲得頁面數據,找到頁面數據中所有的部落格鏈接,存入部落格鏈接的set集合

我們先看看再blog列表頁面中的blog鏈接

匹配/luo4105/art……的正則如下

private String artlUrl = "/luo4105/article/details/[0-9]{8,8}";	//部落格utl的正則表達式

功能程式碼

private String artlUrl = "/luo4105/article/details/[0-9]{8,8}";								//部落格utl的正則表達式  /**   * 添加搜索部落格目錄的部落格鏈接   * @param blogListURL 部落格目錄地址   * @param artlUrls    存放部落格訪問地址的集合   * @throws IOException   */  public void addBlogUrl(String blogListURL, Set<String> artlUrls) throws IOException {  	InputStream is = HttpUtil.doGet(blogListURL);  	String pageStr = StreamUtil.inputStreamToString(is, "UTF-8");  	is.close();  	Pattern pattern = Pattern.compile(artlUrl);  	Matcher matcher = pattern.matcher(pageStr);  	while (matcher.find()) {  		String e = matcher.group(0);  		System.out.println("成功添加部落格地址:" + e);  		artlUrls.add(e);  	}  }

4.遍歷部落格鏈接的set集合,訪問所有部落格鏈接

程式碼如下

@Test  public void visitBlog() throws IOException {  	addBlogUrl();  	/** 這裡可以寫循環 **/  		for(String blogUrl : blogUrls) {  			String artlUrl = csdnBlogUrl + blogUrl;  			InputStream is = HttpUtil.doGet(artlUrl);  			if (is != null) {  				System.out.println(artlUrl + "訪問成功");  			}  			is.close();  		}    /** 這裡可以寫循環 **/  }

貼出所有程式碼

訪問URL並拿到響應工具類

public class HttpUtil {      public static InputStream doGet(String urlstr) throws IOException {         URL url= new URL(urlstr);         HttpURLConnection conn= (HttpURLConnection) url.openConnection();         conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36");         InputStream inputStream= conn.getInputStream();         return inputStream;      }  }

將響應的InputStream轉成String的工具類

public class StreamUtil {      public static String inputStreamToString(InputStream is, String charset) throws IOException {         byte[] bytes = new byte[1024];         int byteLength = 0;         StringBuffer sb = new StringBuffer();         while((byteLength = is.read(bytes)) != -1) {             sb.append(new String(bytes, 0, byteLength, charset));         }         return sb.toString();      }  }

blog刷訪問類

/**   * @author 逝夕誠   * 刷csdn部落格訪問量   */  public class AddCsdnBlogPV {    	private String csdnBlogUrl = "http://blog.csdn.net/";  	private String firstBlogListPageUrl = "http://blog.csdn.net/luo4105";				//部落格主頁  	private String nextPagePanner = "<a href="/luo4105/article/list/[0-9]{1,10}">下一頁</a>";	//下一頁的正則表達式  	private String nextPageUrlPanner = "/luo4105/article/list/[0-9]{1,10}";				//下一頁Url的正則表達式  	private String artlUrl = "/luo4105/article/details/[0-9]{8,8}";					//部落格utl的正則表達式    	private Set<String> blogListPageUrls = new TreeSet<>();  	private Set<String> blogUrls = new TreeSet<>();    	@Test  	public void visitBlog() throws IOException {  		addBlogUrl();  			for(String blogUrl : blogUrls) {  				String artlUrl = csdnBlogUrl + blogUrl;  				InputStream is = HttpUtil.doGet(artlUrl);  				if (is != null) {  					System.out.println(artlUrl + "訪問成功");  				}  				is.close();  			}  	}    	/**  	 * @throws IOException  	 * 載入所有的bolg地址  	 */  	@Test  	public void addBlogUrl() throws IOException {  		blogListPageUrls.add(firstBlogListPageUrl);  		addBlogListPageUrl(firstBlogListPageUrl, blogListPageUrls);  		for (String bolgListUrl : blogListPageUrls) {  			addBlogUrl(bolgListUrl, blogUrls);  		}  	}    	/**  	 * 通過下一頁,遍歷所有部落格目錄頁面鏈接  	 * @param pageUrl  	 * @param pagelistUrls  	 * @throws IOException  	 */  	public void addBlogListPageUrl(String pageUrl, Set<String> pagelistUrls) throws IOException {  		InputStream is = HttpUtil.doGet(pageUrl);  		String pageStr = StreamUtil.inputStreamToString(is, "UTF-8");  		is.close();  		Pattern nextPagePattern = Pattern.compile(nextPagePanner);  		Matcher nextPagematcher = nextPagePattern.matcher(pageStr);  		if (nextPagematcher.find()) {  			nextPagePattern = Pattern.compile(nextPageUrlPanner);  			nextPagematcher = nextPagePattern.matcher(nextPagematcher.group(0));  			if (nextPagematcher.find()) {  				pagelistUrls.add(csdnBlogUrl + nextPagematcher.group(0));  				System.out.println("成功添加部落格列表頁面地址:" + csdnBlogUrl + nextPagematcher.group(0));  				addBlogListPageUrl(csdnBlogUrl + nextPagematcher.group(0), pagelistUrls);  			}  		}  	}    	/**  	 * 添加搜索部落格目錄的部落格鏈接  	 * @param blogListURL 部落格目錄地址  	 * @param artlUrls    存放部落格訪問地址的集合  	 * @throws IOException  	 */  	public void addBlogUrl(String blogListURL, Set<String> artlUrls) throws IOException {  		InputStream is = HttpUtil.doGet(blogListURL);  		String pageStr = StreamUtil.inputStreamToString(is, "UTF-8");  		is.close();  		Pattern pattern = Pattern.compile(artlUrl);  		Matcher matcher = pattern.matcher(pageStr);  		while (matcher.find()) {  			String e = matcher.group(0);  			System.out.println("成功添加部落格地址:" + e);  			artlUrls.add(e);  		}  	}  }

結果

結語

功能實現主要技術點是

1.java http的請求、響應。

2.正則的匹配。

今天是星期六又是520,我又孤獨的坐在寶安圖書館三樓期刊後面的角落,又默默的寫著這無聊到蛋疼的程式、以及教別人如何寫這無聊到蛋疼的部落格,念及此不覺潸然淚下。

程式碼地址:https://code.csdn.net/luo4105/study_http/tree/history/src/main/java/com/lc/https/AddCsdnBlogPV.java