系列文章
- 秋名山澗--給班長(zhǎng)的開車APP -- 用爬蟲webmagic爬取數(shù)據(jù)(一)
- 秋名山澗--給班長(zhǎng)的開車APP -- 用MySql結(jié)合JDBC保存數(shù)據(jù)到數(shù)據(jù)庫(kù)(二)
- 秋名山澗--給班長(zhǎng)的開車APP -- 用Rest API制作API接口(三)
小喇叭開篇啦!?繁埂诵盼!
開發(fā)環(huán)境
Win 10
IDEA Ultimate 2017.1.4
JDK 1.8.0_102
你要是想詳細(xì)研究Webmagic爬蟲框架可以去 WebMagic doc頁(yè)仔細(xì)研讀死嗦,目前此框架個(gè)人覺得少個(gè)爬數(shù)據(jù)完成時(shí)的回調(diào)馋记。跨晴。兼犯。
無異議就開始咯乳规,我覺得要寫詳細(xì)點(diǎn)....
新建一個(gè)Java Project
其他的都不用點(diǎn)啦强衡,直接新建
為了可以用Mevan加載jar包擦秽,對(duì)著項(xiàng)目點(diǎn)右鍵
將Maven打勾,確定漩勤,然后項(xiàng)目中多出pom.xml文件
將這個(gè)復(fù)制到pom.xml文件中感挥,然后保存,打開自動(dòng)導(dǎo)包(會(huì)有自動(dòng)提示)越败,稍等完成webmagic的導(dǎo)包
<project
.....
<dependencies>
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-core</artifactId>
<version>0.7.2</version>
</dependency>
<dependency>
<groupId>us.codecraft</groupId>
<artifactId>webmagic-extension</artifactId>
<version>0.7.2</version>
</dependency>
</dependencies>
...
</project>
根據(jù)WebMagic的使用說明触幼, 新建一個(gè)類MeizituRepoProcessor實(shí)現(xiàn)接口PageProcessor
public class MeituRepoProcessor implements PageProcessor {
public MeituRepoProcessor() {
}
public void process(Page page) {
}
public Site getSite() {
return null;
}
}
現(xiàn)在還什么都沒有
1 分析網(wǎng)站結(jié)構(gòu)
www.meizitu.com的網(wǎng)頁(yè)結(jié)構(gòu)是
可以看到主要內(nèi)容是在id為container的div里
現(xiàn)在我們需要的數(shù)據(jù)在id為pagecontent的div里
進(jìn)一步的分析我們可以看到我們要的數(shù)據(jù)在pagecontent里面id為maincontent的盒子里
這個(gè)是底部的別的頁(yè)的網(wǎng)址,結(jié)構(gòu)是/a/more_1.html究飞,/a/more_2.html置谦,/a/more_3.html....
接著再看圖片的信息堂鲤,這個(gè)就是我們最終要爬的數(shù)據(jù)之一
再舉個(gè)栗子
觀察網(wǎng)址規(guī)律
發(fā)現(xiàn)都是 www.meizitu.com/a/****(數(shù)字).html
正則表達(dá)式表示為:(http://www.meizitu.com/a/(\d{4}).html)
點(diǎn)進(jìn)大圖,比如媒峡,http://www.meizitu.com/a/5551.html
可以看到瘟栖,圖片的網(wǎng)址都在img標(biāo)簽的src屬性下
類似 mm.howkuai.com/wp-content/uploads/****(一系列數(shù)字日期表示).jpg
正則表達(dá)式為: (http://mm.howkuai.com/wp-content/uploads/(.*).jpg)
--
2 根據(jù)這些規(guī)律
MeituRepoProcessor中添加實(shí)現(xiàn)代碼
public class MeituRepoProcessor implements PageProcessor {
public MeituRepoProcessor() {
}
private Site site = Site.me().setRetryTimes(3).setSleepTime(1000);
public void process(Page page) {
//選取網(wǎng)頁(yè)中css為id為maincontent的div,然后選取所有鏈接丝蹭,再用正則表達(dá)式過濾掉
List<String> urls = page.getHtml().css("#maincontent").links().regex("(http:\\/\\/www\\.meizitu\\.com\\/a\\/(\\d{4})\\.html)").all();
//將待爬取的網(wǎng)址加到抓取隊(duì)列池中
page.addTargetRequests(urls);
//這個(gè)是提取的主站www.meizitu.com的每個(gè)突變的title慢宗,用xpath表示,這個(gè)可以在調(diào)試?yán)锩嫦鹿?jié)點(diǎn)右鍵copy的到xpath地址奔穿,后面的這里的意思是id為maincontent的容器(這里是div)中的第一個(gè)盒子下的第一個(gè)盒子中的h2標(biāo)簽下的a標(biāo)簽的文字
page.putField("webTitle", page.getHtml().xpath("http://*[@id=\"maincontent\"]/div[1]/div[1]/h2/a/text()"));
//先用xpath過濾到具體大的塊(id為picture的容器中的p標(biāo)簽的img標(biāo)簽的src屬性值)镜沽,接著正則表達(dá)式提取出來(規(guī)律)
page.putField("picName", page.getHtml().xpath("http://*[@id=\"picture\"]/p/img[@src]").regex("(http:\\/\\/mm\\.howkuai\\.com\\/wp-content\\/uploads\\/(.*)\\.jpg)").all());
if (page.getResultItems().get("picName") == null) {
//如果當(dāng)前獲取到的圖片網(wǎng)址為null,那么跳到網(wǎng)址池中下一個(gè)網(wǎng)址抓取
page.setSkip(true);
}
//抓取底部的更多頁(yè)面的地址
List<String> nextUrls = page.getHtml().regex("(\\/a\\/more_(.*?)\\.html)").all();
page.putField("nextUrls", nextUrls);
//添加到池中
page.addTargetRequests(nextUrls);
}
public Site getSite() {
return site;
}
public static void main(String[] args) {
Spider.create(new MeituRepoProcessor())
.addUrl("http://www.meizitu.com/")
.addPipeline(new ConsolePipeline())
.thread(1)
.run();
}
}
注釋很清楚了贱田,就不多BB了
這里加了main方法缅茉,在Idea中可以在方法體里右鍵run main()方法測(cè)試,數(shù)據(jù)會(huì)全部打印到控制臺(tái)男摧。
可以看到數(shù)據(jù)都是在數(shù)組里面蔬墩,第一個(gè)框是更多頁(yè)的地址,第二個(gè)框是title耗拓,第三個(gè)是圖片的url地址數(shù)組拇颅。
可以看到目前為止,數(shù)據(jù)已經(jīng)爬取成功了乔询,本篇的(一)可以結(jié)束了
然后哎呀圖片地址都搞出來了樟插,我就是控幾不住我記幾啊,然后就寫了個(gè)工具類全部下載下來了竿刁。黄锤。。啊哈哈哈啊哈
新建一個(gè)類叫做PineLineTest實(shí)現(xiàn)PineLine接口
public class PileLineTest implements Pipeline {
public PileLineTest() {
System.out.println("到大這里1");
}
int downLoadPosition = 1;
public void process(ResultItems resultItems, Task task) {
System.out.println("圖片抓取頁(yè)為:" + resultItems.getRequest().getUrl());
List<String> urls = resultItems.get("picName");
System.out.println("抓取圖片序號(hào)為" + downLoadPosition + "開始進(jìn)入下載");
try {
for (int i = 0; i < urls.size(); i++) {
DownLoadImage.downLoad(urls.get(i), "pic" + i + ".jpg", "D:\\webmagic\\SpiderA\\pic" + downLoadPosition);
}
downLoadPosition++;
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("抓取圖片序號(hào)為" + downLoadPosition + "下載結(jié)束");
}
}
工具類DownLoadImage 如下
package utils;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
/**
* Created by Niwa on 2017/7/2.
*/
public class DownLoadImage {
public static void downLoad(String urlString, String fileName, String savePath) throws IOException {
URL url = new URL(urlString);
URLConnection con = url.openConnection();
con.setRequestProperty("User-Agent","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11");
con.setConnectTimeout(5 * 1000);
InputStream is = con.getInputStream();
byte[] bs = new byte[1024];
int len;
File sf = new File(savePath);
if (!sf.exists()) {
sf.mkdirs();
}
OutputStream os = new FileOutputStream(sf.getPath() + "\\" + fileName);
while ((len = is.read(bs)) != -1) {
os.write(bs, 0, len);
}
os.close();
is.close();
System.out.println(urlString + "下載成功");
}
}
接著去main方法里把
.addPipeline(new ConsolePipeline())
換成
.addPipeline(new PileLineTest())
運(yùn)行
3 注意事項(xiàng)
如果爬取的太快食拜,可能會(huì)導(dǎo)致服務(wù)器403禁止訪問鸵熟,這個(gè)時(shí)候換個(gè)IP地址就可以了
最大能力去模擬瀏覽器的人為操作,比如爬一個(gè)數(shù)據(jù)休息隨機(jī)秒负甸,爬完一個(gè)數(shù)據(jù)更換IP接著爬
跳轉(zhuǎn)到(二)
參考
爬蟲:webmagic
正則表達(dá)式學(xué)習(xí):正則表達(dá)式學(xué)習(xí)
全世界晚安流强!
The End !