webmagic爬取博客园所有文章

最近学习了下webmagic,学webmagic是因为想折腾下爬虫,但是自己学java的,又不想太费功夫,所以webmagic是比较好的选择了。

写了几个demo,源码流程大致看了一遍。想着把博客园的文章列表爬下来吧。

首页显示的就是第一页文章的列表,

但是翻页按钮不是链接,而是动态的地址:

实际请求的地址及参数:

针对这个动态页面的情况,有两种解决方案:

1. webmagic模拟post请求,获取返回页面。

 1 public class CnblogsSpider implements PageProcessor {
 2
 3     private Site site = Site.me().setRetryTimes(3).setSleepTime(1000).setTimeOut(10000)
 4             .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
 5
 6     public static final String URL_LIST = "https://www.cnblogs.com/mvc/AggSite/PostList.aspx";
 7
 8     public static int pageNum = 1;
 9
10     public void process(Page page) {
11
12         if (page.getUrl().regex("^https://www\\.cnblogs\\.com$").match()) {
13             try {
14                 page.addTargetRequests(page.getHtml().xpath("//*[@id=\"post_list\"]/div/div[@class=‘post_item_body‘]/h3/a/@href").all());
15                 pageNum++;
16              //模拟post请求
17                 Request req = new Request();
18                 req.setMethod(HttpConstant.Method.POST);
19                 req.setUrl("https://www.cnblogs.com/mvc/AggSite/PostList.aspx");
20                 req.setRequestBody(HttpRequestBody.json("{CategoryType: ‘SiteHome‘, ParentCategoryId: 0, CategoryId: 808, PageIndex: " + pageNum
21                         + ", TotalPostCount: 4000,ItemListActionName:‘PostList‘}", "utf-8"));
22                 page.addTargetRequest(req);
23             } catch (Exception e) {
24                 e.printStackTrace();
25             }
26         } else if (page.getUrl().regex(URL_LIST).match() && pageNum <= 200) {
27             try {
28                 Thread.sleep(5000);
29                 List<String> urls = page.getHtml().xpath("//*[@class=‘post_item‘]//div[@class=‘post_item_body‘]/h3/a/@href").all();
30                 page.addTargetRequests(urls);
31                 //模拟post请求
32                 Request req = new Request();
33                 req.setMethod(HttpConstant.Method.POST);
34                 req.setUrl("https://www.cnblogs.com/mvc/AggSite/PostList.aspx");
35                 req.setRequestBody(HttpRequestBody.json("{CategoryType: ‘SiteHome‘, ParentCategoryId: 0, CategoryId: 808, PageIndex: " + ++pageNum
36                         + ", TotalPostCount: 4000,ItemListActionName:‘PostList‘}", "utf-8"));
37                 page.addTargetRequest(req);
38                 System.out.println("CurrPage:" + pageNum + "#######################################");
39
40             } catch (Exception e) {
41                 e.printStackTrace();
42             }
43         } else {
44             // 获取页面需要的内容,这里只取了标题,其他信息同理。
45             System.out.println("抓取的内容:" + page.getHtml().xpath("//a[@id=‘cb_post_title_url‘]/text()").get());
46         }
47     }
48
49     public Site getSite() {
50         return site;
51     }
52
53     public static void main(String[] args) {
54         Spider.create(new CnblogsSpider()).addUrl("https://www.cnblogs.com").thread(3).run();
55     }
56 }

2.使用webmagic-selenium

 1 public class SeleniumCnblogsSpider implements PageProcessor {
 2
 3     private Site site = Site.me().setRetryTimes(3).setSleepTime(1000).setTimeOut(10000)
 4             .addHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
 5
 6     public static final String URL_LIST = "https://www\\.cnblogs\\.com/#p\\d{1,3}";
 7
 8     public static int pageNum = 1;
 9
10     public void process(Page page) {
11
12
13         if (page.getUrl().regex("^https://www\\.cnblogs\\.com$").match()) {//爬取第一页
14             try {
15                 page.addTargetRequests(page.getHtml().xpath("//*[@id=\"post_list\"]/div/div[@class=‘post_item_body‘]/h3/a/@href").all());
16
17                 pageNum++;
18                 page.addTargetRequest("https://www.cnblogs.com/#p2");
19             } catch (Exception e) {
20                 e.printStackTrace();
21             }
22         } else if (page.getUrl().regex(URL_LIST).match() && pageNum <= 200) {//爬取2-200页,一共有200页
23             try {
24                 List<String> urls = page.getHtml().xpath("//*[@class=‘post_item‘]//div[@class=‘post_item_body‘]/h3/a/@href").all();
25                 page.addTargetRequests(urls);
26
27                 page.addTargetRequest("https://www.cnblogs.com/#p" + ++pageNum);
28                 System.out.println("CurrPage:" + pageNum + "#######################################");
29
30             } catch (Exception e) {
31                 e.printStackTrace();
32             }
33         } else {
34             // 获取页面需要的内容
35             System.out.println("抓取的内容:" + page.getHtml().xpath("//a[@id=‘cb_post_title_url‘]/text()").get());
36         }
37     }
38
39     public Site getSite() {
40         return site;
41     }
42
43     public static void main(String[] args) {
44         System.setProperty("selenuim_config", "D:/config.ini");//配置文件,我用的webmagic0.7.2,低版本可能不需要该文件,但也不支持phantomjs.
45         Downloader downloader = new SeleniumDownloader();//调用seleniumdownloader,这个downlaoder可以驱动selenium,phantomjs等方式下载,由config.ini配置
46         downloader.setThread(10);
47         Spider.create(new SeleniumCnblogsSpider()).setDownloader(downloader).addUrl("https://www.cnblogs.com").thread(10).runAsync();
48     }
49 }

另附我的config.ini和pom文件:

 1 # What WebDriver to use for the tests
 2 driver=phantomjs
 3 #driver=firefox
 4 #driver=chrome
 5 #driver=http://localhost:8910
 6 #driver=http://localhost:4444/wd/hub
 7
 8 # PhantomJS specific config (change according to your installation)
 9 #phantomjs_exec_path=/Users/Bingo/bin/phantomjs-qt5
10 phantomjs_exec_path=d:/phantomjs.exe
11 #phantomjs_driver_path=/Users/Bingo/Documents/workspace/webmagic/webmagic-selenium/src/main.js
12 phantomjs_driver_loglevel=DEBUG
 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 2     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 3     <modelVersion>4.0.0</modelVersion>
 4     <groupId>com.summit</groupId>
 5     <artifactId>WebMagicDemo</artifactId>
 6     <version>0.0.1-SNAPSHOT</version>
 7
 8     <dependencies>
 9         <dependency>
10             <groupId>us.codecraft</groupId>
11             <artifactId>webmagic-core</artifactId>
12             <version>0.7.2</version>
13         </dependency>
14         <dependency>
15             <groupId>us.codecraft</groupId>
16             <artifactId>webmagic-extension</artifactId>
17             <version>0.7.2</version>
18         </dependency>
19         <dependency>
20             <groupId>us.codecraft</groupId>
21             <artifactId>webmagic-selenium</artifactId>
22             <version>0.7.2</version>
23         </dependency>
24         <dependency>
25             <groupId>org.seleniumhq.selenium</groupId>
26             <artifactId>selenium-java</artifactId>
27             <version>2.41.0</version>
28         </dependency>
29     </dependencies>
30 </project>

如果依赖版本与此不一致,可能会出问题。

后记:

  本文主要记录了我在解决webmagic爬取动态页面的心得。

  方法1在可以获取动态访问地址的情况下用,比如通过调试工具,我可以找到第二页实际的访问地址是:https://www.cnblogs.com/mvc/AggSite/PostList.aspx,用这种方法实测效率比较高。但复杂场景下不推荐。

  方法2主要是针对复杂场景,在实际地址很难找或者隐藏,网站有反扒措施的情况下通常很好用,因为它是模拟的实际的浏览器,比较耗费资源,效率比方法1低 。

  webmagic0.7.2 支持selenium (chrome),phantomjs的模拟浏览器行为的方式获取页面。我在方法2中使用的是phantomjs下载的。selenium 的方式我也试过,但是每次调用下载就会弹出浏览器窗口,很是不爽,也没找到如何解决,所以就不推荐了。

抓取结果截图:

时间: 2024-10-01 07:55:20

webmagic爬取博客园所有文章的相关文章

python爬取博客园首页文章

先上代码,比较长. 1 # -*- coding=utf-8 -*- 2 __author__ = 'lhyz' 3 4 import urllib 5 import re 6 import socket 7 import time 8 import os 9 10 #使用当前时间创建文件夹 11 ISOTIMEFORMAT='%Y-%m-%d-%X' 12 times=time.strftime( ISOTIMEFORMAT, time.localtime() ) 13 dir='./%s'%

Python爬虫爬取博客园并保存

Python爬虫爬取博客园并保存        爬取博客园指定用户的文章修饰后全部保存到本地 首先定义爬取的模块文件: crawlers_main.py 执行入口 url_manager.py url管理器 download_manager.py 下载模块 parser_manager.py html解析器(解析html需要利用的内容) output_manager.py 输出html网页全部内容文件(包括css,png,js等) crawlers_main.py 执行入口 1 # coding

.NET Core 实现定时抓取博客园首页文章信息并发送到邮箱

前言 大家好,我是晓晨.许久没有更新博客了,今天给大家带来一篇干货型文章,一个每隔5分钟抓取博客园首页文章信息并在第二天的上午9点发送到你的邮箱的小工具.比如我在2018年2月14日,9点来到公司我就会收到一封邮件,是2018年2月13日的博客园首页的文章信息.写这个小工具的初衷是,一直有看博客的习惯,但是最近由于各种原因吧,可能几天都不会看一下博客,要是中途错过了什么好文可是十分心疼的哈哈.所以做了个工具,每天归档发到邮箱,妈妈再也不会担心我错过好的文章了.为什么只抓取首页?因为博客园首页文章

java爬虫爬取博客园数据

网络爬虫 编辑 网络爬虫(又称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本.另外一些不常使用的名字还有蚂蚁.自动索引.模拟程序或者蠕虫. 网络爬虫按照系统结构和实现技术,大致可以分为以下几种类型:通用网络爬虫(General Purpose Web Crawler).聚焦网络爬虫(Focused Web Crawler).增量式网络爬虫(Incremental Web Crawler).深层网络爬虫(Deep We

爬虫实战【1】使用python爬取博客园的某一篇文章

第一次实战,我们以博客园为例. Cnblog是典型的静态网页,通过查看博文的源代码,可以看出很少js代码,连css代码也比较简单,很适合爬虫初学者来练习. 博客园的栗子,我们的目标是获取某个博主的所有博文,今天先将第一步. 第一步:已知某一篇文章的url,如何获取正文? 举个栗子,我们参考'农民伯伯'的博客文章吧,哈哈.他是我关注的一个博主. http://www.cnblogs.com/over140/p/4440137.html 这是他的一篇名为"[读书笔记]长尾理论"的文章. 我

【Python3 爬虫】爬取博客园首页所有文章

首先,我们确定博客园首页地址为:https://www.cnblogs.com/ 我们打开可以看到有各种各样的文章在首页,如下图: 我们以上图标记的文章为例子吧!打开网页源码,搜索Docker,搜索结果如下图: 从上图后红色标记部分可以看出,我们使用正则表达式即可匹配该网址,我们匹配到该网址之后,将该网址对应的内容下载到到底进行存储. 实现代码 import urllib.request import re """ 爬取cnblogs首页所有的文章 ""&

Python - 爬取博客园某一目录下的随笔 - 保存为docx

1 #coding:utf-8 2 import requests 3 from bs4 import BeautifulSoup 4 import MySQLdb 5 6 7 def get_html(url): 8 ''' 9 获取页面HTML源码,并返回 10 ''' 11 html = requests.get(url) 12 content = html.text.encode('utf-8') 13 return content 14 15 def get_blog_html_lis

nodejs爬取博客园的博文

其实写这篇文章,我是很忐忑的,因为爬取的内容就是博客园的,万一哪个顽皮的小伙伴拿去干坏事,我岂不成共犯了? 好了,进入主题. 首先,爬虫需要用到的模块有: express ejs superagent (nodejs里一个非常方便的客户端请求代理模块) cheerio (nodejs版的jQuery) 前台布局使用bootstrap 分页插件使用 twbsPagination.js 完整的爬虫代码,在我的github中可以下载.主要的逻辑代码在 router.js 中. 1. 爬取某个栏目第1页

Scrapy爬取博客园精华区内容

程序爬取目标 获取博客园精华区文章的标题.标题链接.作者.作者博客主页链接.摘要.发布时间.评论数.阅读数和推荐数,并存储到MongoDB中. 程序环境 已安装scrapy 已安装MongoDB 创建工程 scrapy startproject cnblogs 在命令提示符中执行上述命令后,会建立一个名为cnblogs的文件夹. 创建爬虫文件 cd cnblogs scrapy genspider cn cnblogs.com 执行上述命令后,会在cnblogs\spiders\下新建一个名为c