標籤:

使用瑞雪採集雲爬蟲採集大眾點評商家信息

前段時間,有個採集大眾點評商家的需求,主要包含以下的信息【圖1】,客戶會給出具體的那個城市,然後採集該城市下所有的美食商家信息。該需求可以使用平台的Pipe模型,共分成6個規則進行採集,每個規則的輸入輸出參數及採集內容,可以參考【圖6】。Pipe模型的好處是,一個任務的輸出數據,作為下一個任務的輸入參數,同時生成多個下一個任務,利用平台的分散式,將若干個任務分派到多個爬蟲機執行,提高執行效率。

圖1,採集信息

圖2,Pipe(管道)模型說明

圖3,各個規則採集的內容

圖4,各個規則採集的內容

圖5,各個規則採集的內容

圖6,各個規則的說明

圖7,分散式任務

import java.util.List;import com.ruixuesoft.crawler.open.*;public class Rule1 implements RxRule { @Override public RxResult execute ( RxTask task , RxCrawler crawler , RxDatabase database ) throws RxCrawlerException { //打開城市的美食首頁 crawler.open ( task.getV1 () ); //點擊更多 RxNode moreNode = crawler.getNodeByXpath ( "//*[@id=classfy]/a[@class=more J_packdown]" ); if ( moreNode != null ) { moreNode.click (); crawler.sleepSeconds ( 1 ); } //抓取所有分類元素列表 List<RxNode> classfyNodeList = crawler.getNodeListByXpath ( "//*[@id=classfy]/a" ); //抓取列表中的每一個分類 if ( classfyNodeList != null && classfyNodeList.size () > 0) { for ( RxNode classfyNode : classfyNodeList) { String url = classfyNode.getAttribute ( "href" );//分類URL String classfyName = classfyNode.getText ();//分類名 //過濾掉非分類名 if("不限".equals ( classfyName ) || "收起".equals ( classfyName ) || "更多".equals ( classfyName )) { continue; } task.log ( classfyName ); task.log ( url ); //設置下一個任務的輸入參數 RxTask newNextRuleTask = new RxTask(); newNextRuleTask.setV1(task.getV2 ());//城市 newNextRuleTask.setV2 ( classfyName );//分類名 newNextRuleTask.setV3 ( url );//分類URL //創建下一個規則的任務 task.createNextRuleTask ( newNextRuleTask ); } } //設置結束code,200為正常結束 RxResult result = new RxResult (); result.setFinishCode ( 200 ); return result; }}

import java.util.List;import com.ruixuesoft.crawler.open.*;public class Rule2 implements RxRule { @Override public RxResult execute ( RxTask task , RxCrawler crawler , RxDatabase database ) throws RxCrawlerException { //打開菜品分類URL crawler.open ( task.getV3 () ); //點擊行政區 RxNode regionNode = crawler.getNodeByXpath ( "//*[@id=J_nav_tabs]/a[2]/span" ); if ( regionNode != null ) { regionNode.click (); crawler.sleepSeconds ( 5 ); } //抓取行政區URL List<RxNode> regionNodeList = crawler.getNodeListByXpath ( "//*[@id=region-nav]/a" ); int regionIndex = 1; if ( regionNodeList != null && regionNodeList.size () > 0 ) { for ( RxNode region : regionNodeList) { String url = region.getAttribute ( "href" );//行政區URL String regionName = region.getText ();//行政區名 //過濾掉非行政區名 if("不限".equals ( regionName ) || "收起".equals ( regionName ) || "更多".equals ( regionName )) { continue; } task.log ( regionName ); task.log ( url ); //設置下一個任務的輸入參數 RxTask newNextRuleTask = new RxTask(); newNextRuleTask.setV1 ( task.getV1 () );//城市 newNextRuleTask.setV2 ( task.getV2 () );//分類名 newNextRuleTask.setV3 ( regionName);//行政區名 newNextRuleTask.setV4 ( (regionIndex++)+"");//第幾個行政區 newNextRuleTask.setV5 ( url );//行政區URL //創建下一個規則的任務 task.createNextRuleTask ( newNextRuleTask ); } } //設置結束code,200為正常結束 RxResult result = new RxResult (); result.setFinishCode ( 200 ); return result; }}

import java.util.List;import com.ruixuesoft.crawler.open.*;public class Rule3 implements RxRule { @Override public RxResult execute ( RxTask task , RxCrawler crawler , RxDatabase database ) throws RxCrawlerException { //打開一級行政區URL crawler.open ( task.getV5() ); crawler.sleepSeconds ( 1 );//等待1秒 //點擊行政區 RxNode regionNode = crawler.getNodeByXpath ( "//*[@id=J_nav_tabs]/a[2]/span" ); if ( regionNode != null ) { regionNode.click (); crawler.sleepSeconds ( 1 ); } //點擊二級行政區 RxNode oneRegionNode = crawler.getNodeByXpath ( " //*[@id=region-nav]/a["+task.getV4 ()+"]/span" ); if ( oneRegionNode != null ) { oneRegionNode.click (); crawler.sleepSeconds ( 1 ); } //再點擊行政區 regionNode = crawler.getNodeByXpath ( "//*[@id=J_nav_tabs]/a[2]/span" ); if ( regionNode != null ) { regionNode.click (); crawler.sleepSeconds ( 1 ); } //點擊更多 RxNode moreNode = crawler.getNodeByXpath ( " //*[@id=region-nav-sub]/a[text()=更多]" ); if ( moreNode != null ) { moreNode.click (); crawler.sleepSeconds ( 1 ); } //抓取二級行政區列表 List<RxNode> bussNodeList = crawler.getNodeListByXpath ( "//*[@id=region-nav-sub]/a" ); //抓取列表中的每一個二級行政區 if ( bussNodeList != null && bussNodeList.size () > 0 ) { for ( RxNode bussNode : bussNodeList) { String url = bussNode.getAttribute ( "href" );//二級行政區URL String bussName = bussNode.getText ();//二級行政區名 //過濾掉非二級行政區名 if("不限".equals ( bussName ) || "收起".equals ( bussName )) { continue; } task.log ( bussName ); task.log ( url ); //設置結束code,二級行政區名是空的,用455標示 if ("".equals(bussName)){ RxResult result = new RxResult (); result.setFinishCode ( 455 ); return result; } //設置下一個任務的輸入參數 RxTask newNextRuleTask = new RxTask(); newNextRuleTask.setV1 ( task.getV1 ());//城市 newNextRuleTask.setV2 ( task.getV3 () );//行政區 newNextRuleTask.setV3 ( bussName );//二級行政區 newNextRuleTask.setV4 ( task.getV2 () );//分類 newNextRuleTask.setV5 ( url );///二級行政區URL //創建下一個規則的任務 task.createNextRuleTask ( newNextRuleTask ); } } //設置結束code,200為正常結束 RxResult result = new RxResult (); result.setFinishCode ( 200 ); return result; }}

import java.util.List;import com.ruixuesoft.crawler.open.*;public class Rule4 implements RxRule { @Override public RxResult execute ( RxTask task , RxCrawler crawler , RxDatabase database ) throws RxCrawlerException { //打開二級行政區URL crawler.open ( task.getV5 () ); //抓取該分類下行政區所有商家的所有頁數節點列表 List<RxNode> rxNodeList = crawler.getNodeListByXpath ( "//div[@class=page]/a[@title=下一頁]/parent::*/a" ); int maxPage = 1;//最大頁數 if ( rxNodeList.size () > 0 ) { for ( RxNode rxNode : rxNodeList ) { if ( rxNode.getText ().contains ( "下一頁" ) ) {//達到最後一個節點,循環結束 break; }else { //賦值給最大頁數 maxPage = Integer.parseInt ( rxNode.getText () ); } } } //生成每個分頁的任務 for ( int i = 0 ; i < maxPage ; i++ ) { //編輯分頁URL String pageUrl = task.getV5 ().trim () + "p" + ( i + 1 ); RxTask newNewRuleTask = new RxTask (); newNewRuleTask.setV1 ( task.getV1() );//城市 newNewRuleTask.setV2 ( task.getV2() );//行政區 newNewRuleTask.setV3 ( task.getV3() );//二級行政區 newNewRuleTask.setV4 ( task.getV4() );//菜系分類 newNewRuleTask.setV5 ( pageUrl );//分頁URL newNewRuleTask.setV6 ( i + 1 + "" );//頁號 //創建下一個規則的任務 task.createNextRuleTask ( newNewRuleTask ); } //設置結束code,200為正常結束 RxResult result = new RxResult (); result.setFinishCode ( 200 ); return result; }}

import java.sql.SQLException;import java.util.*;import com.ruixuesoft.crawler.open.*;public class Rule5 implements RxRule { @Override public RxResult execute ( RxTask task , RxCrawler crawler , RxDatabase database ) throws RxCrawlerException { crawler.open ( task.getV5 () );// 分頁URL // 商家列表DIV RxNode shopAllListDivNode = crawler.getNodeByXpath ( "//*[@id=shop-all-list]" ); List<RxNode> lstDiv = shopAllListDivNode.getNodeListByXpath ( "//ul/li//div[@class=tit]" ); // 處理一個商家的信息 for ( RxNode div : lstDiv ) { RxNode link = div.getNodeByXpath ( "./a[1]" ); String href = link.getAttribute ( "href" ); // 大眾點評商家ID String shopId = href.substring ( href.lastIndexOf ( "/" ) + 1 ); String shopUrl = href;//商家URL // 商家名稱 String shopName = link.getAttribute ( "title" ) ; //入庫 String sql = "insert into `shop_base_info_test`(`city`,`region`,`street`,`dish_type`,`shop_id`,`shop_name`,`url`, `create_time`) values(?, ?, ?, ?, ?, ?, ?, current_timestamp())"; Object[] values = { task.getV1 () , task.getV2 () , task.getV3 () , task.getV4 () , shopId ,shopName , shopUrl}; int seq = database.insert ( sql , values ); // 使用商家基本信息SEQ,創建下一個任務 RxTask newNewRuleTask = new RxTask (); newNewRuleTask.setV1 ( shopId ); newNewRuleTask.setV2 ( shopName ); newNewRuleTask.setV3 ( shopUrl ); task.createNextRuleTask ( newNewRuleTask ); } // 設置結束code,200為正常結束 RxResult result = new RxResult (); result.setFinishCode ( 200 ); return result; }}

import java.math.BigInteger;import java.sql.Connection;import java.sql.SQLException;import java.util.*;import com.ruixuesoft.crawler.open.*;public class Rule6 implements RxRule { @Override public RxResult execute ( RxTask task , RxCrawler crawler , RxDatabase database ) throws RxCrawlerException { // 打開頁面 crawler.open ( task.getV3() ); // 商家圖片 String shopImageUrl = crawler.getNodeByXpath ( "//*[@id=aside]/div[1]/div/descendant::a/img" ).getAttribute ( "src" ); // 商家評星 String shopStar = crawler.getNodeByXpath ( "//*[@id=basic-info]/div[1]/span[1]" ).getAttribute ( "title" ); // 人均消費 String averageCost = crawler.getNodeByXpath ( "//*[@id=basic-info]/div[1]/span[contains(.,人均)]" ).getText (); // 口味評分 String flavor = crawler.getNodeByXpath ( "//*[@id=comment_score]/span[contains(.,口味)]" ).getText (); // 環境評分 String environment = crawler.getNodeByXpath ( "//*[@id=comment_score]/span[contains(.,環境)]" ).getText (); // 服務評分 String service = crawler.getNodeByXpath ( "//*[@id=comment_score]/span[contains(.,服務)]" ).getText (); // 商家地址 String address = crawler.getNodeByXpath ( "//*[@id=basic-info]/div[2]/span[@itemprop=street-address]" ).getAttribute ( "title" ); // 商家電話 String tel = crawler.getNodeByXpath ( "//*[@id=basic-info]/p[@class=expand-info tel]" ).getText (); // 商家詳細信息入庫 String sql = "INSERT INTO shop_detail_info_test ( shop_id,shop_name,shop_image,shop_star,average_cost," + "flavor,environment,service,address,tel,create_time) VALUES ( ?, ?, ?, ?, ?, ?, ?,?, ?, ?,now())"; Object[] values = { task.getV1() , task.getV2() , shopImageUrl , shopStar , averageCost , flavor , environment , service , address , tel }; database.insert ( sql , values ); //設置結束code,200為正常結束 RxResult result = new RxResult (); result.setFinishCode ( 200 ); return result; }}

推薦閱讀:

智多星:年賺 100-1000 萬省大師APP 項目內部獨家講解完整版
為何《銀翼殺手2049》值9.7分?
劉強東為什麼說如果十年後互聯網還是BAT 對國家是種不幸?
劉強東的成功裡面,你學到了什麼?
軟文寫作方法?

TAG:互聯網 |