一、爬虫实例
爬取csdn个人主页,先进入主页,我们发现列表页是这样的规则
https://blog\\.csdn\\.net/qq_41061437/article/details/1
只有后面的数字会发生变化,因此可以用正则表达式:
"https://blog\\.csdn\\.net/qq_41061437/article/list/\\d,定义一个URL_LIST:
public static final String URL_LIST = "https://blog\\.csdn\\.net/qq_41061437/article/list/\\d";
单独点击一篇文章,发现URL地址是这样的:https://blog.csdn.net/qq_41061437/article/details/82258431,每一篇文章只有最后的数字会改变,我们可以定义一个URL_POST,后面利用正则表达式来表示:
public static final String URL_POST = "https://blog\\.csdn\\.net/qq_41061437/article/details/\\d{1,}";
定义抓取规则:
private Site site = Site
.me()
.setDomain("blog.csdn.net")
.setSleepTime(3000)
.setUserAgent(
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");
我们需要先抓取列表页,列表页抓取利用XPath,XPath获取方式如图:
然后写规则:
page.addTargetRequests(page.getHtml().xpath("//*[@id=\"mainBox\"]/main/div[2]").links().regex(URL_POST).all());
page.addTargetRequests(page.getHtml().links().regex(URL_LIST).all());
接着就是抓取文章内容,这里只抓取文章的标题和内容,也是利用XPath来获取,方式同上:
现在可以编写规则:
page.putField("title", page.getHtml().xpath("//*[@id=\"mainBox\"]/main/div[1]/div/div/div[1]/h1"));
page.putField("content", page.getHtml().xpath("//*[@id=\"article_content\"]"));
接着只需要定义main方法启动就行,目的是利用Spider将各个组件组织起来:
Spider.create(new csdnSpider()).addUrl("https://blog.csdn.net/qq_41061437/article/list/1")
.run();
完整代码如下:
package com.matai03;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;
public class csdnSpider implements PageProcessor {
public static final String URL_LIST = "https://blog\\.csdn\\.net/qq_41061437/article/list/\\d";
public static final String URL_POST = "https://blog\\.csdn\\.net/qq_41061437/article/details/\\d{1,}";
private Site site = Site
.me()
.setDomain("blog.csdn.net")
.setSleepTime(3000)
.setUserAgent(
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31");
@Override
public void process(Page page) {
//列表页
if (page.getUrl().regex(URL_LIST).match()) {
page.addTargetRequests(page.getHtml().xpath("//*[@id=\"mainBox\"]/main/div[2]").links().regex(URL_POST).all());
page.addTargetRequests(page.getHtml().links().regex(URL_LIST).all());
//文章页
} else {
page.putField("title", page.getHtml().xpath("//*[@id=\"mainBox\"]/main/div[1]/div/div/div[1]/h1"));
page.putField("content", page.getHtml().xpath("//*[@id=\"article_content\"]"));
}
}
@Override
public Site getSite() {
return site;
}
public static void main(String[] args) {
Spider.create(new csdnSpider()).addUrl("https://blog.csdn.net/qq_41061437/article/list/1")
.run();
}
}
二、页面元素抽取
对于下载到的Html页面,你如何从中抽取到你想要的信息?WebMagic里主要使用了三种抽取技术:XPath、正则表达式和CSS选择器。另外,对于JSON格式的内容,可使用JsonPath进行解析。
①XPath
XPath本来是用于XML中获取元素的一种查询语言,但是用于Html也是比较方便的。例如:
page.getHtml().xpath("//*[@id=\"mainBox\"]/main/div[2]")
这段代码使用了XPath,它的意思是“查找所有id属性为'mainBox'下的mian节点下的第二个div的元素。 对应的Html是这样子的:
②CSS选择器
CSS选择器是与XPath类似的语言。如果大家做过前端开发,肯定知道$('h1.entry-title')这种写法的含义。客观的说,它比XPath写起来要简单一些,但是如果写复杂一点的抽取规则,就相对要麻烦一点。
③正则表达式
正则表达式则是一种通用的文本抽取语言。
page.addTargetRequests(page.getHtml().links().regex("(https://github\\.com/\\w+/\\w+)").all());
这段代码就用到了正则表达式,它表示匹配所有"https://github.com/code4craft/webmagic"这样的链接。
④JsonPath
JsonPath是于XPath很类似的一个语言,它用于从Json中快速定位一条内容。WebMagic中使用的JsonPath格式可以参考这里:https://code.google.com/p/json-path/
三、链接的发现
有了处理页面的逻辑,我们的爬虫就接近完工了!
但是现在还有一个问题:一个站点的页面是很多的,一开始我们不可能全部列举出来,于是如何发现后续的链接,是一个爬虫不可缺少的一部分。
page.addTargetRequests(page.getHtml().links().regex("(https://github\\.com/\\w+/\\w+)").all());
这段代码分为两部分,page.getHtml().links().regex("(https://github\\.com/\\w+/\\w+)").all()
用于获取所有满足"(https:/ /github\.com/\w+/\w+)"这个正则表达式的链接,page.addTargetRequests()
则将这些链接加入到待抓取的队列中去。