网络爬虫框架Webmagic
1?談談網絡爬蟲
?1.1 什么是網絡爬蟲
在大數據時代,信息的采集是一項重要的工作,而互聯網中的數據是海量的,如果單純靠人力進行信息采集,不僅低效繁瑣,搜集的成本也會提高。如何自動高效地獲取互聯網中我們感興趣的信息并為我們所用是一個重要的問題,而爬蟲技術就是為了解決這些問題而生的。
網絡爬蟲(Web crawler)也叫做網絡機器人,可以代替人們自動地在互聯網中進行數據信息的采集與整理。它是一種按照一定的規則,自動地抓取萬維網信息的程序或者腳本,可以自動采集所有其能夠訪問到的頁面內容,以獲取或更新這些網站的內容和檢索方式。
從功能上來講,爬蟲一般分為數據采集,處理,儲存三個部分。爬蟲從一個或若干初始網頁的URL開始,獲得初始網頁上的URL,在抓取網頁的過程中,不斷從當前頁面上抽取新的URL放入隊列,直到滿足系統的一定停止條件。
?
1.2 網絡爬蟲可以做什么
我們初步認識了網絡爬蟲,網絡爬蟲具體可以做什么呢?
?a.可以實現搜索引擎
?b.大數據時代,可以讓我們獲取更多的數據源。
?c.快速填充測試和運營數據
?d.為人工智能提供訓練數據集
?
1.3 網絡爬蟲常用的技術(Java)
1.3.1 底層實現?HttpClient + Jsoup
?HttpClient 是?Apache Jakarta Common 下的子項目,用來提供高效的、最新的、功能豐富的支持?HTTP 協議的客戶端編程工具包,并且它支持?HTTP 協議最新的版本和建議。?HttpClient 已經應用在很多的項目中,比如?Apache Jakarta 上很著名的另外兩個開源項目?Cactus 和?HTMLUnit 都使用了?HttpClient。更多信息請關注http://hc.apache.org/
??jsoup 是一款Java 的HTML解析器,可直接解析某個URL地址、HTML文本內容。它提供了一套非常省力的API,可通過DOM,CSS以及類似于jQuery的操作方法來取出和操作數據。
?
1.3.2 開源框架?Webmagic
?webmagic是一個開源的Java爬蟲框架,目標是簡化爬蟲的開發流程,讓開發者專注于邏輯功能的開發。webmagic的核心非常簡單,但是覆蓋爬蟲的整個流程,也是很好的學習爬蟲開發的材料。
?
?
? webmagic的主要特色:
?a.完全模塊化的設計,強大的可擴展性。
?b.核心簡單但是涵蓋爬蟲的全部流程,靈活而強大,也是學習爬蟲入門的好材料。
?c.提供豐富的抽取頁面API。
?d.無配置,但是可通過POJO+注解形式實現一個爬蟲。
?e.?支持多線程。
?f.?支持分布式。
?g.支持爬取js動態渲染的頁面。
?h.無框架依賴,可以靈活的嵌入到項目中去。
?
2 爬蟲框架Webmagic
?2.1 架構解析
?WebMagic項目代碼分為核心和擴展兩部分。核心部分(webmagic-core)是一個精簡
?的、模塊化的爬蟲實現,而擴展部分則包括一些便利的、實用性的功能。擴展部分(webmagic-extension)提供一些便捷的功能,例如注解模式編寫爬蟲等。同時內置了一些常用的組件,便于爬蟲開發。
?WebMagic的設計目標是盡量的模塊化,并體現爬蟲的功能特點。這部分提供非常簡單、靈活的API,在基本不改變開發模式的情況下,編寫一個爬蟲。
?WebMagic的結構分為Downloader、PageProcessor、Scheduler、Pipeline四大組件,并由Spider將它們彼此組織起來。這四大組件對應爬蟲生命周期中的下載、處理、管
?理和持久化等功能。而Spider則將這幾個組件組織起來,讓它們可以互相交互,流程化的執行,可以認為Spider是一個大的容器,它也是WebMagic邏輯的核心。
?
?
四大組件
?a.Downloader
?Downloader負責從互聯網上下載頁面,以便后續處理。WebMagic默認使用了ApacheHttpClient作為下載工具。
?
?b.PageProcessor
?PageProcessor負責解析頁面,抽取有用信息,以及發現新的鏈接。WebMagic使用Jsoup作為HTML解析工具,并基于其開發了解析XPath的工具Xsoup。
?在這四個組件中,PageProcessor對于每個站點每個頁面都不一樣,是需要使用者定制的部分。
?
c.Scheduler
?Scheduler負責管理待抓取的URL,以及一些去重的工作。WebMagic默認提供了JDK的內存隊列來管理URL,并用集合來進行去重。也支持使用Redis進行分布式管理。
?
d.Pipeline
?Pipeline負責抽取結果的處理,包括計算、持久化到文件、數據庫等。WebMagic默認提供了“輸出到控制臺”和“保存到文件”兩種結果處理方案。
?
?
2.2 PageProcessor
?需求:編寫爬蟲程序,爬取csdn中博客--工人智能的內容
?
2.2.1 爬取頁面全部內容
?
https://blog.csdn.net/nav/ai
?
(1)創建工程,引入依賴
?
<dependency><groupId>us.codecraft</groupId><artifactId>webmagic‐core</artifactId><version>0.7.3</version></dependency><dependency><groupId>us.codecraft</groupId><artifactId>webmagic‐extension</artifactId><version>0.7.3</version></dependency>?
(2)編寫類實現網頁內容的爬取
?
import us.codecraft.webmagic.Page;import us.codecraft.webmagic.Site;import us.codecraft.webmagic.Spider;import us.codecraft.webmagic.processor.PageProcessor; /** *爬取類*/public class MyProcessor implements PageProcessor {public void process(Page page) {System.out.println(page.getHtml().toString());}public Site getSite() {return Site.me().setSleepTime(100).setRetryTimes(3);}public static void main(String[] args) {Spider.create( new MyProcessor() ).addUrl("https://blog.csdn.net").run();}}?
??Spider是爬蟲啟動的入口。在啟動爬蟲之前,我們需要使用一個PageProcessor創建一個Spider對象,然后使用run()進行啟動。
?方法**? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 說明**? ? ? ? ? ? ? ? ? ? ? ? 示例**?
create(PageProcessor)? ? ? 創建Spider? ? ? ? ? ? ?Spider.create(new GithubRepoProcessor())
?
?同時Spider的其他組件(Downloader、Scheduler、Pipeline)都可以通過set方法來進行設置。
?Page代表了從Downloader下載到的一個頁面——可能是HTML,也可能是JSON或者其他文本格式的內容。Page是WebMagic抽取過程的核心對象,它提供一些方法可供抽取、結果保存等。
?Site用于定義站點本身的一些配置信息,例如編碼、HTTP頭、超時時間、重試策略等、代理等,都可以通過設置Site對象來進行配置。
?方法**? ? ? ? ? ? ? 說明** 示例**
setCharset(String) 設置編碼 site.setCharset("utf-8")
?
2.2.2 爬取指定內容(XPath)
?
??如果我們想爬取網頁中部分的內容,需要指定xpath。
?XPath,即為XML路徑語言(XMLPathLanguage),它是一種用來確定XML文檔中某部分位置的語言。XPath 使用路徑表達式來選取?XML 文檔中的節點或者節點集。這些路徑表達式和我們在常規的電腦文件系統中看到的表達式非常相似。?
?我們通過指定xpath來抓取網頁的部分內容
?
System.out.println(page.getHtml().xpath("//* [@id=\"nav\"]/div/div/ul/li[5]/a").toString());以上代碼的含義:id為nav的節點下的div節點下的div節點下的ul下的第5個li節點下的a節點
?
看一下輸出結果
?
<a href="/nav/ai">人工智能</a>?
2.2.3 添加目標地址
?
我們可以通過添加目標地址,從種子頁面爬取到更多的頁面
?
?
?
public void?process(Page page) {
?
page.addTargetRequests(?page.getHtml().links().all() );//將當前頁面
?
里的所有鏈接都添加到目標頁面中
?
public?void?process(Page?page)?{page.addTargetRequests(?page.getHtml().links().all()?);//將當前頁面 里的所有鏈接都添加到目標頁面中System.out.println(page.getHtml().xpath("//* [@id=\"nav\"]/div/div/ul/li[5]/a").toString());}?
運行后發現好多地址都出現在控制臺
?
2.2.4 目標地址正則匹配
?需求:只提取csdn的文章詳細頁內容,并提取標題
?
import us.codecraft.webmagic.Page;import us.codecraft.webmagic.Site;import us.codecraft.webmagic.Spider;import us.codecraft.webmagic.processor.PageProcessor; /** *爬取類*/public class MyProcessor implements PageProcessor {public void process(Page page) {//page.addTargetRequests( page.getHtml().links().all() );//將當前頁 面里的所有鏈接都添加到目標頁面中// page.addTargetRequests(page.getHtml().links().regex("https://blog.csdn.net/[a‐z 0‐9 ‐]+/article/details/[0‐9]{8}").all() ); System.out.println(page.getHtml().xpath("//* [@id=\"mainBox\"]/main/div[1]/div[1]/h1/text()").toString());}public Site getSite() {return Site.me().setSleepTime(100).setRetryTimes(3);}public static void main(String[] args) {Spider.create( new MyProcessor()).addUrl("https://blog.csdn.net/nav/ai").run();}}?
?
2.3 Pipeline
2.3.1 ConsolePipeline 控制臺輸出
?
/***?爬取類*/ public?class?MyProcessor?implements?PageProcessor?{public?void?process(Page?page)?{//page.addTargetRequests(?page.getHtml().links().all()?);//將當前頁 面里的所有鏈接都添加到目標頁面中// ????????page.addTargetRequests( page.getHtml().links().regex("https://blog.csdn.net/[a‐z?0‐9 ‐]+/article/details/[0‐9]{8}").all()?);//System.out.println(page.getHtml().xpath("//* [@id=\"mainBox\"]/main/div[1]/div[1]/h1/text()").toString());page.putField("title",page.getHtml().xpath("//* [@id=\"mainBox\"]/main/div[1]/div[1]/h1/text()").toString());}public?Site?getSite()?{return?Site.me().setSleepTime(100).setRetryTimes(3);}public?static?void?main(String[]?args)?{Spider.create(?new?MyProcessor()?).addUrl("https://blog.csdn.net").addPipeline(new?ConsolePipeline()).run();} }?
?
2.3.2 FilePipeline 文件保存
?
public?static?void?main(String[]?args)?{Spider.create(?new?MyProcessor()?).addUrl("https://blog.csdn.net").addPipeline(new?ConsolePipeline()).addPipeline(new?FilePipeline("e:/data"))//以文件方式保存 ????????????????.run();}?
2.3.3 JsonFilePipeline
?以json方式保存
?
public?static?void?main(String[]?args)?{Spider.create(?new?MyProcessor()?).addUrl("https://blog.csdn.net").addPipeline(new?ConsolePipeline()).addPipeline(new?FilePipeline("e:/data")).addPipeline(new?JsonFilePipeline("e:/json"))//?以json方式保 存.run();}?
2.3.4 定制Pipeline
?如果以上Pipeline都不能滿足你的需要,你可以定制Pipeline
(1)創建類MyPipeline實現接口Pipeline
?
import?us.codecraft.webmagic.ResultItems; import?us.codecraft.webmagic.Task; import?us.codecraft.webmagic.pipeline.Pipeline; public?class?MyPipeline?implements?Pipeline?{public?void?process(ResultItems?resultItems,?Task?task)?{String?title=resultItems.get("title");System.out.println("我的定制的?title:"+title);}(2)修改main方法
public?static?void?main(String[]?args)?{Spider.create(?new?MyProcessor()?).addUrl("https://blog.csdn.net").addPipeline(new?ConsolePipeline()).addPipeline(new?FilePipeline("e:/data")).addPipeline(new?JsonFilePipeline("e:/json")).addPipeline(new?MyPipeline())//定制化輸出 ????????????????.run();}?
2.4 Scheduler
我們剛才完成的功能,每次運行可能會爬取重復的頁面,這樣做是沒有任何意義的。Scheduler(URL管理) 最基本的功能是實現對已經爬取的URL進行標示。可以實現URL的增量去重。
?目前scheduler主要有三種實現方式:
?1)內存隊列 QueueScheduler
?2)文件隊列 FileCacheQueueScheduler
?3) Redis隊列?RedisScheduler
?
2.4.1 內存隊列
?使用setScheduler來設置Scheduler
?
public?static?void?main(String[]?args)?{Spider.create(?new?MyProcessor()?).addUrl("https://blog.csdn.net").setScheduler(new?QueueScheduler()).run();}?
2.4.2 文件隊列
?使用文件保存抓取URL,可以在關閉程序并下次啟動時,從之前抓取到的URL繼續抓取
(1)創建文件夾E:\scheduler
?(2)修改代碼
public?static?void?main(String[]?args)?{Spider.create(?new?MyProcessor()?).addUrl("https://blog.csdn.net")//.setScheduler(new?QueueScheduler())//設置內存隊列.setScheduler(new FileCacheQueueScheduler("E:\\scheduler"))//設置文件隊列 ????????????????.run();}運行后文件夾E:\scheduler會產生兩個文件blog.csdn.net.urls.txt和?blog.csdn.net.cursor.txt
?
2.4.3 Redis隊列
?使用Redis保存抓取隊列,可進行多臺機器同時合作抓取
?(1)運行redis服務端
?(2)修改代碼
?
public?static?void?main(String[]?args)?{Spider.create(?new?MyProcessor()?).addUrl("https://blog.csdn.net")//.setScheduler(new?QueueScheduler())//設置內存隊列//.setScheduler(new FileCacheQueueScheduler("E:\\scheduler"))//設置文件隊列.setScheduler(new?RedisScheduler("127.0.0.1"))//設置Redis隊 列.run();}?
3 csdn文章爬取
?3.1 需求分析
?每日某時間段整從CSDN博客中爬取文檔,存入文章數據庫中。
?3.2 頻道設置
??資訊? ? https://blog.csdn.net/nav/news
人工智能? https://blog.csdn.net/nav/ai
?區塊鏈 https://blog.csdn.net/nav/blockchain
數據庫 https://blog.csdn.net/nav/db
前端 https://blog.csdn.net/nav/web
編程語言 https://blog.csdn.net/nav/lang
?
向數據庫tensquare_article的tb_channel表中添加記錄
?
?
3.3 代碼編寫
?3.3.1 模塊搭建
?(1)創建模塊tensquare_article_crawler ,引入依賴
?
<dependency><groupId>us.codecraft</groupId><artifactId>webmagic‐core</artifactId><version>0.7.3</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j‐log4j12</artifactId></exclusion></exclusions></dependency><dependency><groupId>us.codecraft</groupId><artifactId>webmagic‐extension</artifactId><version>0.7.3</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring‐boot‐starter‐data‐jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql‐connector‐java</artifactId></dependency><dependency><groupId>com.tensquare</groupId><artifactId>tensquare_common</artifactId><version>1.0‐SNAPSHOT</version></dependency>?
?
(2)創建配置文件application.yml
server:port:?9014 spring:application:?name:?tensquare‐crawler?#指定服務名datasource:?driverClassName:?com.mysql.jdbc.Driverurl:?jdbc:mysql://127.0.0.1:3306/tensquare_article? characterEncoding=UTF8username:?rootpassword:?123456jpa:database:?MySQLshow‐sql:?true redis:host:?127.0.0.1?
(3)創建啟動類
?
@SpringBootApplication @EnableScheduling public?class?CrawlerApplication?{@Value("${redis.host}") ? private?String?redis_host; ???public?static?void?main(String[]?args)?{ ??? SpringApplication.run(CrawlerApplication.class,?args); ??????? } ??? @Bean ??? public?IdWorker?idWorkker(){ ??? return?new?IdWorker(1,?1); ??????? } ???@Bean ? public?RedisScheduler?redisScheduler(){ ??? return?new?RedisScheduler(redis_host); ??????? } ??? }?
(4)實體類及數據訪問接口
?
3.3.2 爬取類
?創建文章爬取類ArticleProcessor
package?com.tensquare.crawler.processor; import?us.codecraft.webmagic.Page; import?us.codecraft.webmagic.Site; import?us.codecraft.webmagic.processor.PageProcessor; /***?文章爬取類*/ @Component public?class?ArticleProcessor?implements?PageProcessor?{@Overridepublic?void?process(Page?page)?{page.addTargetRequests(page.getHtml().links().regex("https://blog.csdn.net/ [a‐z?0‐9?‐]+/article/details/[0‐9]{8}").all());String?title=?page.getHtml().xpath("//* [@id=\"mainBox\"]/main/div[1]/div[1]/h1/text()").get();String?content=?page.getHtml().xpath("//* [@id=\"article_content\"]/div/div[1]").get();//獲取頁面需要的內容System.out.println("標題:"+title?);System.out.println("內容:"+content?);if(title!=null?&&?content!=null){??//如果有標題和內容page.putField("title",title);page.putField("content",content);}else{page.setSkip(true);//跳過 ????????}}@Overridepublic?Site?getSite()?{return?Site.me().setRetryTimes(3000).setSleepTime(100);} }?
?3.3.3 入庫類
?創建文章入庫類ArticleDbPipeline ,負責將爬取的數據存入數據庫
?
package?com.tensquare.crawler.pipeline; import?com.tensquare.crawler.dao.ArticleDao; import?com.tensquare.crawler.pojo.Article; import?org.springframework.beans.factory.annotation.Autowired; import?org.springframework.stereotype.Repository; import?us.codecraft.webmagic.ResultItems; import?us.codecraft.webmagic.Task; import?us.codecraft.webmagic.pipeline.Pipeline; import?util.IdWorker; import?java.util.Map; /***?入庫類*/ @Component public?class?ArticleDbPipeline?implements?Pipeline?{@Autowiredprivate?ArticleDao?articleDao;@Autowiredprivate?IdWorker?idWorker;public?void?setChannelId(String?channelId)?{this.channelId?=?channelId;}private?String?channelId;//頻道ID ????@Overridepublic?void?process(ResultItems?resultItems,?Task?task)?{????String?title?=?resultItems.get("title");String?content=?resultItems.get("content");Article?article=new?Article();article.setId(idWorker.nextId()+"");article.setChannelid(channelId);article.setTitle(title);article.setContent(content);articleDao.save(article);} }?
ReusltItems 相當于一個Map,它保存PageProcessor處理的結果,供Pipeline使用。它的API與Map很類似,值得注意的是它有一個字段?skip?,若設置為true,則不應被Pipeline處理。
?
3.3.4 任務類
?創建任務類
?
package?com.tensquare.crawler.task; import?com.tensquare.crawler.pipeline.ArticleDbPipeline; import?com.tensquare.crawler.pipeline.ArticleTxtPipeline; import?com.tensquare.crawler.processor.ArticleProcessor; import?org.springframework.beans.factory.annotation.Autowired; import?org.springframework.scheduling.annotation.Scheduled; import?org.springframework.stereotype.Component; import?us.codecraft.webmagic.Spider; import?us.codecraft.webmagic.scheduler.RedisScheduler; /***?文章任務類*/ @Component public?class?ArticleTask?{@Autowiredprivate?ArticleDbPipeline?articleDbPipeline;@Autowiredprivate?ArticleTxtPipeline?articleTxtPipeline;@Autowiredprivate?RedisScheduler?redisScheduler;@Autowiredprivate?ArticleProcessor?articleProcessor;/***?爬取ai數據*/@Scheduled(cron="0?54?21?*?*??")public?void?aiTask(){System.out.println("爬取AI文章");Spider?spider?=?Spider.create(articleProcessor);spider.addUrl("https://blog.csdn.net/nav/ai");articleTxtPipeline.setChannelId("ai");articleDbPipeline.setChannelId("ai");spider.addPipeline(articleDbPipeline);spider.addPipeline(articleTxtPipeline);spider.setScheduler(redisScheduler);spider.start();}/***?爬取db數據*/@Scheduled(cron="20?17?11?*?*??")public?void?dbTask(){System.out.println("爬取DB文章");Spider?spider?=?Spider.create(articleProcessor);spider.addUrl("https://blog.csdn.net/nav/db");articleTxtPipeline.setChannelId("db");spider.addPipeline(articleTxtPipeline);spider.setScheduler(redisScheduler);spider.start();}/***?爬取web數據*/@Scheduled(cron="20?27?11?*?*??")public?void?webTask(){System.out.println("爬取WEB文章");Spider?spider?=?Spider.create(articleProcessor);spider.addUrl("https://blog.csdn.net/nav/web");articleTxtPipeline.setChannelId("web");spider.addPipeline(articleTxtPipeline);spider.setScheduler(redisScheduler);spider.start();} }?
?
4 CSDN用戶數據爬取
?4.1 需求分析
?從csdn中爬取用戶昵稱和頭像,存到用戶表,頭像圖片存儲到本地
?4.2 代碼編寫
?4.2.1 模塊搭建
?(1)創建工程tensquare_user_crawler。pom.xml引入依賴
?
<dependency><groupId>us.codecraft</groupId><artifactId>webmagic‐core</artifactId><version>0.7.3</version><exclusions><exclusion><groupId>org.slf4j</groupId><artifactId>slf4j‐log4j12</artifactId></exclusion></exclusions></dependency><dependency><groupId>us.codecraft</groupId><artifactId>webmagic‐extension</artifactId><version>0.7.3</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring‐boot‐starter‐data‐jpa</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql‐connector‐java</artifactId></dependency><dependency><groupId>com.tensquare</groupId><artifactId>tensquare_common</artifactId><version>1.0‐SNAPSHOT</version></dependency>?
(2)創建配置文件application.yml
?
server:port:?9015 spring:application:?name:?tensquare‐user‐crawler?#指定服務名datasource:?driverClassName:?com.mysql.jdbc.Driverurl:?jdbc:mysql://127.0.0.1:3306/tensquare_user?characterEncoding=UTF8 ????username:?rootpassword:?123456jpa:database:?MySQLshow‐sql:?true redis:host:?127.0.0.1?
(3)創建啟動類
?
@SpringBootApplication @EnableScheduling public?class?UserCrawlerApplication?{@Value("${redis.host}") ? private?String?redis_host; ???public?static?void?main(String[]?args)?{ ??? SpringApplication.run(CrawlerApplication.class,?args); ??????? } ??? @Bean ??? public?IdWorker?idWorkker(){ ??? return?new?IdWorker(1,?1); ??????? } ???@Bean ? public?RedisScheduler?redisScheduler(){ ??? return?new?RedisScheduler(redis_host); ??????? } ??? }?
(4)實體類及數據訪問接口
?
4.2.2 爬取類
?
package?com.tensquare.usercrawler.processor; import?org.springframework.stereotype.Component; import?us.codecraft.webmagic.Page; import?us.codecraft.webmagic.Site; import?us.codecraft.webmagic.processor.PageProcessor; /***?文章爬取類*/ @Component public?class?UserProcessor?implements?PageProcessor?{@Overridepublic?void?process(Page?page)?{page.addTargetRequests(page.getHtml().links().regex("https://blog.csdn.net/ [a‐z?0‐9?‐]+/article/details/[0‐9]{8}").all());String?nickname=?page.getHtml().xpath("//* [@id=\"uid\"]/text()").get();String?image=?page.getHtml().xpath("//* [@id=\"asideProfile\"]/div[1]/div[1]/a").css("img","src").toString();if(nickname!=null?&&?image!=null){??//如果有昵稱和頭像page.putField("nickname",nickname);page.putField("image",image);}else{page.setSkip(true);//跳過 ????????}}@Overridepublic?Site?getSite()?{return?Site.me().setRetryTimes(3000).setSleepTime(100);} }?
4.2.3 下載工具類
?將工具類拷貝至tensquare_common工程的util包下
?
package?util; import?java.io.*; import?java.net.URL; import?java.net.URLConnection; /***?下載工具類*/ public?class?DownloadUtil?{public?static?void?download(String?urlStr,String?filename,String savePath)?throws?IOException?{URL?url?=?new?URL(urlStr);//打開url連接URLConnection?connection?=?url.openConnection();//請求超時時間connection.setConnectTimeout(5000);//輸入流InputStream?in?=?connection.getInputStream();//緩沖數據byte?[]?bytes?=?new?byte[1024];//數據長度int?len;//文件File?file?=?new?File(savePath);if(!file.exists())file.mkdirs();OutputStream?out??=?new FileOutputStream(file.getPath()+"\\"+filename);//先讀到bytes中while?((len=in.read(bytes))!=‐1){//再從bytes中寫入文件out.write(bytes,0,len);}//關閉IOout.close();in.close();} }?
4.2.4 入庫類
?
?
package?com.tensquare.usercrawler.pipeline; import?com.tensquare.usercrawler.dao.UserDao; import?com.tensquare.usercrawler.pojo.User; import?org.springframework.beans.factory.annotation.Autowired; import?org.springframework.stereotype.Component; import?us.codecraft.webmagic.ResultItems; import?us.codecraft.webmagic.Task; import?us.codecraft.webmagic.pipeline.Pipeline; import?util.DownloadUtil; import?util.IdWorker; import?java.io.IOException; @Component public?class?UserPipeline?implements?Pipeline?{@Autowiredprivate?IdWorker?idWorker;@Autowiredprivate?UserDao?userDao;@Overridepublic?void?process(ResultItems?resultItems,?Task?task)?{User?user=new?User();user.setId(idWorker.nextId()+"");user.setNickname(resultItems.get("nickname"));String?image?=?resultItems.get("image");//圖片地址String?fileName?=?image.substring(image.lastIndexOf("/")+1);user.setAvatar(fileName);userDao.save(user);//下載圖片try?{DownloadUtil.download(image,fileName,"e:/userimg");}?catch?(IOException?e)?{e.printStackTrace();}} }?
4.2.5 任務類
?
package?com.tensquare.usercrawler.task; import?com.tensquare.usercrawler.pipeline.UserPipeline; import?com.tensquare.usercrawler.processor.UserProcessor; import?org.springframework.beans.factory.annotation.Autowired; import?org.springframework.scheduling.annotation.Scheduled; import?org.springframework.stereotype.Component; import?us.codecraft.webmagic.Spider; import?us.codecraft.webmagic.scheduler.RedisScheduler; /***?用戶爬取任務類*/ @Component public?class?UserTask?{@Autowiredprivate?RedisScheduler?redisScheduler;@Autowiredprivate?UserPipeline?userPipeline;@Autowiredprivate?UserProcessor?userProcessor;/***?爬取用戶數據*/@Scheduled(cron="0?56?22?*?*??")public?void?userTask(){System.out.println("爬取用戶");Spider?spider?=?Spider.create(userProcessor);spider.addUrl("https://blog.csdn.net");spider.addPipeline(userPipeline);spider.setScheduler(redisScheduler);spider.start();} }?
轉載于:https://www.cnblogs.com/daiwei1981/p/9990240.html
總結
以上是生活随笔為你收集整理的网络爬虫框架Webmagic的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Fast Stone超好用的截图工具,可
- 下一篇: MDT跨网段UEFI部署系统