jsoup爬虫实战详解之新浪
**
jsoup爬蟲實戰詳解之新浪
**
今天分享一個之前困擾了一段時間的關于jsoup爬取新浪網頁信息的踩坑總結。
在實現以上功能的之前我門首先要了解兩個重點:1.關于jsoup的爬取細節以及教程,爬取時所要了解jsoup的相關標簽:具體的自己大家感興趣的可以自行百度去詳細了解下對應的教程。
2.第二點就是我們要了解爬取對面網站的頁面構造,現在大體分為HTML形式的展示,還有一種是通過js異步加載所呈現頁面效果的形式,js異步加載相對而言比較復雜,今天我們著重講解下以html形式展示的jsoup實戰使用,今天就以新浪為網頁為例子進行講解。
第一步:引入相應的pom文件內容:
第二步:了解新浪網頁的基礎的構造
我們進入新浪網頁,例如我們點進到體育分類欄,進入體育分類頁面右擊查看網頁源碼,我們可以看到
對應的列表的構造基本是ul>li>a,我們就可以獲取到對應標題進入詳情的鏈接
上述我們可以獲取對應分類的列表信息,我們隨便點一個進入到對應的詳情頁面繼續看下頁面的構造情況:
對應的詳情的基本結構就是以class為article為主導的基本數據的構造。今天我門就基本講解將對應的標題內容信息進行抓取為功能的主導實現
上述就是新浪的對應的頁面構造,下面我們直接進入業務代碼:
1.通過模擬CHROME覽器來獲取頁面的document信息,代碼如下
url為對應的抓取的對應的路徑信息,useHtmlUnit為是否使用HtmlUnit此處我們可以傳值為false。
public static Document getHtmlFromUrl(String url, boolean useHtmlUnit) {Document document = null;if (!useHtmlUnit) {try {document = Jsoup.connect(url)// 模擬火狐瀏覽器.userAgent("Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)").get();} catch (Exception e) {}} else {// 模擬CHROME覽器WebClient webClient = new WebClient(BrowserVersion.CHROME);webClient.getOptions().setJavaScriptEnabled(true);// 1 啟動JSwebClient.getOptions().setCssEnabled(false);// 2 禁用Css,可避免自動二次請求CSS進行渲染webClient.getOptions().setActiveXNative(false);webClient.getOptions().setRedirectEnabled(true);// 3 啟動重定向webClient.setCookieManager(new CookieManager());// 4 啟動cookie管理webClient.setAjaxController(new NicelyResynchronizingAjaxController());// 5 啟動ajax代理webClient.getOptions().setThrowExceptionOnScriptError(false);// 6 js運行錯誤時,是否拋出異常webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);webClient.getOptions().setUseInsecureSSL(true);// 忽略ssl認證webClient.getOptions().setTimeout(10000);// 7 設置超時/*** 設置代理 ProxyConfig proxyConfig = webClient.getOptions().getProxyConfig(); proxyConfig.setProxyHost(listserver.get(0));* proxyConfig.setProxyPort(Integer.parseInt(listserver.get(1)));*/HtmlPage htmlPage = null;try {htmlPage = webClient.getPage(url);webClient.waitForBackgroundJavaScript(10000);webClient.setJavaScriptTimeout(10000);String htmlString = htmlPage.asXml();return Jsoup.parse(htmlString);} catch (Exception e) {e.printStackTrace();} finally {webClient.close();}}return document;}第二步核心代碼
/*** * @param: @param 對應抓取的路徑信息:http://sports.sina.com.cn/假定新浪的體育路徑* @param: @param 對應標簽id 自己的對應的標簽id,此處代表新浪* @param: @param 上線數* @param: @param 對應網頁的標簽規則:此處我們假定為:ul > li > a* @param: @return 數量標簽如果為0則爬取結束 * @return: List<Map<String,String>>*/private static List<Map<String,String>> pullNews(String tagUrl,Integer tag,Integer num,String regex) {//獲取網頁Document html= null;try {html = BaseJsoupUtil.getHtmlFromUrl(tagUrl, false);} catch (Exception e) {}List<Map<String,String>> returnList = new ArrayList<>();//定義返回的list//jsoup獲取<a>標簽,不同的地址匹配不同的匹配規則Elements newsATags = null;//可以理解為上述的,上述我們關于體育的第一個頁面的規則基本為:ul > li > aif(Utils.notBlank(regex)) {newsATags = html.select(regex);}else {System.out.println(tagUrl+"采集規則未設置");return returnList;}//當規則不適用時if(newsATags.isEmpty()) {System.out.println(tagUrl+"規則不適用");return returnList;}//從<a>標簽中抽取urlList<Map<String,String>> list = new ArrayList<>();//定義存儲url的list//遍歷我們體育專題的列表信息來獲取通過對應的url獲取對應的詳情信息for (Element a : newsATags) {String articleTitle=a.text();//獲取當前標題信息String url = a.attr("href");//獲取對應的標題的路徑,也就是我上述所說的跳轉對應詳情的路徑,我們通過進入詳情來抓取我們想要的文章標題,圖片等信息if(url.contains("html")) {if(url.indexOf("http") == -1) {url = "http:" + url;}Map<String,String> map = new HashMap<>();map.put("url", url);map.put("title", articleTitle);list.add(map);}else {continue; } }//根據url訪問頁面獲取內容for(Map<String,String> m :list) {Document newsHtml = null;try {//通過模擬器獲取對應路徑下的html信息,此處的url就是對應的詳情的鏈接,通過模擬器獲取對應的頁面信息內容newsHtml = BaseJsoupUtil.getHtmlFromUrl(m.get("url"), false);String title=m.get("title");//獲取標題Elements newsContent=null;String data;newsContent=newsHtml.select(".article");//這里就是我上述講解信息的第二個說的jsoup通過標簽來進行信息抓取,上述的為class為article的抓取規則if(newsContent!=null) { String content=newsContent.toString();//獲取對應的內容信息//篇幅太短的文章不需要if(content.length() < 200) {//過濾過長的文章break;}//時間過濾if(Utils.isBlank(newsHtml.select(".date").text())) {data=newsHtml.select(".time").text().replaceAll("年", "-").replaceAll("月", "-").replaceAll("日", "");}else{data=newsHtml.select(".date").text().replaceAll("年", "-").replaceAll("月", "-").replaceAll("日", "");}//指定路徑時間過濾if(tagUrl.equals("http://collection.sina.com.cn/")) {data=newsHtml.select(".titer").text().replaceAll("年", "-").replaceAll("月", "-").replaceAll("日", "");}else if(tagUrl.equals("https://finance.sina.com.cn/stock/") || tagUrl.equals("http://blog.sina.com.cn/lm/history/")) {data=newsHtml.select(".time SG_txtc").text().replaceAll("年", "-").replaceAll("月", "-").replaceAll("日", "").replaceAll("(", "").replaceAll(")", "");}//獲取到圖片信息List<String> imgSrcList = BaseJsoupUtil.getImgSrcList(content);String coverImg = "";if(!imgSrcList.isEmpty()) {if(num == 0) {break;//已達設定的采集數量上限}num --;for(String url : imgSrcList){String imgUrl = BaseJsoupUtil.downloadUrl(url.indexOf("http") == -1?"http:" + url:url);content = Utils.isBlankStr(content)?content:content.replace(url, imgUrl);if(Utils.isBlank(coverImg))coverImg = imgUrl.replace(FileConst.QINIU_FILE_HOST+"/", "");}//獲取到我們想要的東西封裝到map里面,這樣就基本結束拉Map<String,String> map = new HashMap<>();map.put("title", title);//標題map.put("date", data);//文章創建時間map.put("content", HtmlCompressor.compress(content));//文章內容map.put("tag", tag.toString());//標簽idmap.put("coverImg", coverImg);//文章封面圖map.put("url", m.get("url"));//urlreturnList.add(map);}}} catch (Exception e) {e.printStackTrace();}}return returnList;}上述就是jsoup抓取的基本邏輯,整體的總結就是熟悉對應jsoup的標簽使用教程,想要抓取頁面的具體規則,知道了這些基本就可以結合自己的業務邏輯來進行信息獲取,這里關于新浪的抓取我們只做技術交流,希望大家不要用于商業使用。好了,今天就到這里了,后期繼續分享自己的踩坑記錄,有什么問題的可以留言。
總結
以上是生活随笔為你收集整理的jsoup爬虫实战详解之新浪的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 系统的Drawable(四)-Layer
- 下一篇: word activex部件不能创建对象