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