java爬取頭條文章中名字圖片
阿新 • • 發佈:2018-12-28
背景描述:
前段時間,我哥讓我給侄女想一個好名字,作為一個工科生,這倒有點難倒我了。隱約記得以前刷頭條的時候刷到過一些好聽的名字,於是便去搜了一下。這一搜不要緊,接下來給我推送的都是關於這方面的文章,而我就毫不客氣地全都收藏了。剛好這兩天閒下來了,便想著把儲存下來。但一看,都收藏了幾十篇文章,且都是圖片,如果一篇篇地去看,然後下載,這無疑就是搬磚。這讓我這種懶人無疑是不能接受了。於是便想著寫一個爬蟲吧,把全部都爬下來。
當然,有的磚必須得搬,比如各個文章的URL地址,這個以目前的能力還不能智慧獲取。首先手動獲取了各篇文章的URL地址,如下圖所示。
在得到文章的URL之後,便開始文章中各個圖片爬取工作了。話不多說,直接放碼。
import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import org.apache.commons.io.FileUtils; import cn.cxd.tools.FileTools; public class DownLoadToutiaoPicture { public static void main(String[] args) throws Exception { String srcPath = "D:/name/url.txt";// 儲存了各個文章URL地址 String dstPath = "D:/name/content.txt";// 儲存了文章中各個圖片的URL String dstDir = "D:/name/";// 最終圖片存放的目錄 File srcFile = new File(srcPath); File dstFile = new File(dstPath); BufferedReader br = new BufferedReader(new FileReader(srcFile)); BufferedWriter bw = new BufferedWriter(new FileWriter(dstFile)); String line = null; while ((null) != (line = br.readLine())) { getContent(bw, line); } line = null; BufferedReader br1 = new BufferedReader(new FileReader(dstFile)); ArrayList<String> totalPicUrlList = new ArrayList<>();// 存放各個圖片的URL while ((null) != (line = br1.readLine())) { ArrayList<String> tmpList = parse(line);// 一篇文章中圖片的URL地址。 totalPicUrlList.addAll(tmpList);// 加入到總list裡面。 } for (int index = 0; index < totalPicUrlList.size(); index++) { // 使用了Apache第三方的common io,既然別人把輪子都造好了,那就發揚拿來主義吧!哈哈哈。。。 FileUtils.copyURLToFile(new URL(totalPicUrlList.get(index)), new File(dstDir + index + ".jpg")); } FileTools.close(br1, bw, br); } /** * 根據文章的URL地址獲取各個圖片的URL。通過分析網頁的原始碼可知,一個圖片的URL完整地址可能分行顯示。而全部圖片的URL都包含在articleInfo裡面, * 因此,本文的方案是把articleInfo裡面的內容全部獲取到本地,然後再解析,即後面的parse()函式。 * * @param bw * @param line * 文章的URL地址連結 * @throws Exception */ private static void getContent(BufferedWriter bw, String line) throws Exception { URL url = new URL(line); // 頭條做了反爬機制,必須將程式偽裝成瀏覽器訪問才行。 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"); BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); // 將articleInfo裡面的內容組裝成一行,方便後面的解析工作。 StringBuilder sb = new StringBuilder(); boolean flag = false; // 這裡建議不要用while((null) != // (line=br.readLine()))來做,極有可能還沒有讀到articleInfo時就為空,導致程式退出。 for (int i = 0; i < 2000; i++) { String input = br.readLine(); if (null != input) { System.out.println(input); if (input.contains("articleInfo")) { System.out.println(input); flag = true; } if (flag == true) { sb.append(input); System.out.println(input); } if (input.contains("groupId")) {// groupId為articleInfo結束後的第一行內容,讀到這表示articleInfo內容已經讀完,則將i置為200以退出迴圈。 i = 2000; } } } bw.write(sb.toString()); bw.newLine(); sb = new StringBuilder(); FileTools.close(br); } /** * 解析出裡面的URL地址,存入list並返回。 * * @param line * 上面提到的articleInfo裡面的內容。 * @return */ private static ArrayList<String> parse(String line) { int len = line.length(); char[] ch = line.toCharArray(); StringBuilder sb = new StringBuilder(); ArrayList<String> picUrlList = new ArrayList<>(); for (int i = 0; i < len - 4; i++) { String tmp = line.substring(i, i + 4); if (tmp.equals("http")) { for (int j = i; j < len; j++) { if (ch[j] != '&') { sb.append(ch[j]); } else { j = len; } } picUrlList.add(sb.toString()); sb = new StringBuilder(); } } return picUrlList; } }
關於遇到的坑已經在程式碼註釋中做了說明。
另外,在程式最後也出現了異常,如下圖所示:
這個還得日後再去深扒。
最後爬取的結果如下圖所示: