webmagic使用总结
1.webmagic 的优点
有较全的文档和较多的使用人群。
使用起来相对简单,理解了一个例子就可以照葫芦画瓢的爬取其他网站。
项目不大,添加依赖不多,操作简单。
有时候需要哪些功能,可以不用自己写,继承一个类就好了。
2.爬取步骤及每个步骤曾遇到的难题。
第一步:分析url,添加相应cookie,header, userAgent等信息。
问题:
(1)cookie部分:
要把所有有用的信息分析出来添加,有的时候把所有的cookie 都添加进去反而不准确,而且对于某些cookie信息较多的网站都添加的话比较麻烦。
(2)header部分:
把所有的request header部分都添加进去就可以了,只有在刚开始学习爬虫的时候因为没有添加header信息而出过错。
(3)userAgent部分:
有些网站会根据userAgent来判断是否是同一款浏览器在刷数据, 所以要为userAgent设置不同的浏览器,每次请求前随机获取一个。而对于某些只限制在手机端访问的,要设置成移动端的userAgent列表。有的网站移动端与PC端的显示的页面是不相同的,所以要确定爬的是哪部分的数据,然后设置地赢得userAgent。
第二步:得到页面,对页面有用的部分进行抽取。
问题:这部分的难点就在于数据的抽取,出过的问题就在于当某个地方获取不到数据的时候(比如XPATH写错),程序就会立即结束也没有任何报错信息,所以数据抽取的时候,要多一步判空的处理。
第三步:将得到的数据存储到db中。
问题:实体类中的变量要与数据库中的字段名称要保持一致。
3.反爬与反反爬
反爬策略:
level1:屏蔽ip 。肉眼检测屏蔽存在异常访问的ip.
level2:每天或每小时超过一定次数屏蔽ip 。
level3:一段时间超过次数弹出验证码,通过则增加几分钟无限制时间。
level4:前端异步加载js,动态加密token 。
level5:更换或者混淆数据内容 。
level6:人工智能反爬 。人工智能ai判断可疑行为,宁可错杀不肯放过
反反爬:
针对level1:设置代理池;
针对level2:设置代理池;
针对level3、level4:登陆后拿到cookie继续爬。
针对Level5: 抓包,模拟Json请求获取,不爬页面。
level6:没敢爬level6的网站。
3.爬虫简介
之前觉得爬虫是一个很厉害的技术,相当于传说中的黑客,只闻其声未见其人的那种类似传说中的存在,所以当我听说我可以学习爬虫的时候也是一脸惊慌,这么厉害的技术我竟然也可以学么?有点跃跃欲试但还是有点担心自己上不了手。后来经过波神的指点开始学习webMagic,然后开始一步步的了解下来,发现其实还蛮简单上手的。
WebMagic简单来说是一个开源的Java爬虫框架,是为了简化爬虫的开发流程,开发者只需要根据需求写好页面抓取的规则。
WebMagic的结构Downloader、PageProcessor、Scheduler、Pipeline四大组件,并由Spider将它们彼此组织起来。这四大组件对应爬虫生命周期中的下载、处理、管理和持久化等功能。Spider将这几个组件组织起来,让他们可以相互交互、流程化的进行,可以认为Spider是一个大的容器,它也是WebMagic逻辑的核心。具体的介绍在官方文档里都有介绍。
附文档链接:http://webmagic.io/
学习WebMagic的第一步也是根据官方文档的介绍,添加了相应的jar包后,再下载官网的源码。因为源码中有很多不同网站的抓取规则,刚看的时候有些费劲,有些晕头转向傻傻分不楚,就去百度别人的简单案例,自己的目标是先实现,然后自己再重写,就这样开始第一个爬虫。
和很多新手一样,爬的是一个比较简单的网页,需求也很简单。能够将其中简单的数据打印出来就好。接下来也根据这段简单代码的示例,目标是将文章的作者打印出来并显示爬取时间。
public class MyProcessor implements PageProcessor {
// 抓取网站的相关配置,包括编码、抓取间隔、重试次数等
private Site site = Site.me().setRetryTimes(3).setSleepTime(100);
private static int count =0;
@Override
public Site getSite() {
return site;
}
@Override
public void process(Page page) {
//判断链接是否符合http://www.cnblogs.com/任意个数字字母-/p/7个数字.html格式
if(!page.getUrl().regex("http://www.cnblogs.com/[a-z 0-9 -]+/p/[0-9]{7}.html").match()){
//加入满足条件的链接
page.addTargetRequests(
page.getHtml().xpath("//*[@id=\"post_list\"]/div/div[@class='post_item_body']/h3/a/@href").all());
}else{
//获取页面需要的内容
System.out.println("抓取的内容:"+
page.getHtml().xpath("//*[@id=\"Header1_HeaderTitle\"]/text()").get()
);
count ++;
}
}
public static void main(String[] args) {
long startTime, endTime;
System.out.println("开始爬取...");
startTime = System.currentTimeMillis();
Spider.create(new MyProcessor()).addUrl("https://www.cnblogs.com/").thread(5).run();
endTime = System.currentTimeMillis();
System.out.println("爬取结束,耗时约" + ((endTime - startTime) / 1000) + "秒,抓取了"+count+"条记录");
}
}
其中有两个核心方法:
public void process(Page page):通过page对象实现爬虫逻辑。addTargetRequests可以添加url到待抓取的队列,page.getHtml().xpath()则是按照某个规则对结果进行抽取
public Site getSite():site对象定义了编码、抓取间隔、重试次数等信息。
以上的代码实现爬虫的时候,有三个重要的内容分别是爬虫的一些基本配置、目标链接的发现以及页面元素的抽取。
基本的配置主要包括网站的一些header以及cookie的配置,在site()这个方法中有对应的添加方式分别为addHeader()和addCookie(),将网站的一些基本信息配置好以后就可以伪装成一个正常的用户进行的正常的访问。
程序的第一步创建一个Spider对象,并添加初始Url;
第二步是目标链接的发现,有可能第一开始添加的url并不是真正你想要获取元素的页面所对应的url,但是可以通过这个url得到,只需要在process这个方法中将目标url添加到待抓区的
队列即可。
第三步为页面元素的抽取。当确定要抓取页面所在的位置之后,可以经过Xpath来取到页面内容,Xpath获取的方式为在chrome审查元素下,选择要需要的部分右键Copy,选择Copy XPath,之后再将内容复制到page.getHtml().xpath()中;
另外还有几种获取元素的方式。
getUrl()可以获得当前url,
addTargetRequests()就是把链接放入等待爬取。
getHtml()获得页面的html元素。