爬虫+基于接口的网络爬虫

上一篇讲了【java爬虫】---爬虫+jsoup轻松爬博客,该方式有个很大的局限性,就是你通过jsoup爬虫只适合爬静态网页,所以只能爬当前页面的所有新闻。如果需要爬一个网站所有信息,就得通过接口,通过改变参数反复调该网站的接口,爬到该网站的所有数据信息。

本博客以爬金色财经新闻信息为对象,去爬取该网站从建站以来发表的所有新闻信息。下面会一步一步讲解。这里重点重点讲思路,最后我会提供完整源码。

第一步:找接口

你要获得该网站所有新闻数据,第一步当然是获得接口,通过接口来获取所有信息。

F12-->Network-->all,找到接口:https://api.jinse.com/v4/information/listcatelogue_key=news&limit=23&information_id=56630&flag=down&version=9.9.9

对这三个参数做个说明:

limit=23   代表每次调用该接口返回23条数据。

information_id=56630  代表下面返回的23条数据是通过大于56630或者小于56630这个ID指来返回数据。

flag=down   代表向下翻页 这里也就是指ID小于56630的23条数据。

 通过postMan测试

输入:https://api.jinse.com/v4/information/list?catelogue_key=news&limit=2&information_id=0&flag=down&version=9.9.9(这里返回两条,id=0这里代表最新的两条数据)

返回json数据格式:

{
"news": 2,
"count": 2,
"total": null,
"top_id": 58300,
"bottom_id": 58325,
"list": [
{
"id": 58300,
"title": "跨越牛熊的摆渡人:看金融IT服务如何助力加密货币交易",
"short_title": "当传统金融IT服务商进入加密货币时代",
"type": 1,
"order": 0,
"is_top": false,
"extra": {
"version": "9.9.9",
"summary": "存量资金与投资者日渐枯竭,如何获取新用户和新资金入场,成为大小交易所都在考虑的问题。而交易深度有限、流动性和行情稳定性不佳,也成为横亘在牛熊之间的一道障碍。",
"published_at": 1532855806,
"author": "临渊",
"author_avatar": "https://img.jinse.com/753430_image20.png",
"author_id": 127939,
"author_level": 1,
"read_number": 27064,
"read_number_yuan": "2.7万",
"thumbnail_pic": "https://img.jinse.com/996033_image1.png",
"thumbnails_pics": [
"https://img.jinse.com/996033"
],
"thumbnail_type": 1,
"source": "金色财经",
"topic_url": "https://m.jinse.com/news/blockchain/219916.html",
"attribute_exclusive": "",
"attribute_depth": "深度",
"attribute_spread": ""
}
},
{
"id": 58325,
"title": "各路大佬怎样看待区块链:技术新武器应寻找新战场",
"short_title": "各路大佬怎样看待区块链:技术新武器应寻找新战场",
"type": 1,
"order": 0,
"is_top": false,
"extra": {
"version": "9.9.9",
"summary": "今年年初由区块链社区引发的讨论热潮,成为全民一时热议的话题,罕有一项技术,能像区块链这样——在其应用还未大范围铺开、被大众直观感知时,就搅起舆论风暴,扰动民众情绪。",
"published_at": 1532853425,
"author": "新浪财经",
"author_avatar": "https://img.jinse.com/581794_image20.png",
"author_id": 94556,
"author_level": 5,
"read_number": 33453,
"read_number_yuan": "3.3万",
"thumbnail_pic": "https://img.jinse.com/995994_image1.png",
"thumbnails_pics": [
"https://img.jinse.com/995994"
],
"thumbnail_type": 1,
"source": "新浪财经",
"topic_url": "https://m.jinse.com/blockchain/219934.html",
"attribute_exclusive": "",
"attribute_depth": "",
"attribute_spread": ""
}
}
]
}

接口返回信息

第二步:通过定时任务开启爬虫工作

@Slf4j
@Component
public class SchedulePressTrigger { @Autowired
private CrawlerJinSeLivePressService crawlerJinSeLivePressService; /**
* 定时抓取金色财经的新闻
*/
@Scheduled(initialDelay = 1000, fixedRate = 600 * 1000)
public void doCrawlJinSeLivePress() { // log.info("开始抓取金色财经新闻, time:" + new Date());
try {
crawlerJinSeLivePressService.start();
} catch (Exception e) {
// log.error("本次抓取金色财经新闻异常", e);
}
// log.info("结束抓取金色财经新闻, time:" + new Date());
}
}

第三步:主要实现类

/**
* 抓取金色财经快讯
* @author xub
* @since 2018/6/29
*/
@Slf4j
@Service
public class CrawlerJinSeLivePressServiceImpl extends AbstractCrawlLivePressService implements
CrawlerJinSeLivePressService { //这个参数代表每一次请求获得多少个数据
private static final int PAGE_SIZE = 15; //这个是真正翻页参数,每一次找id比它小的15个数据(有写接口是通过page=1,2来进行翻页所以比较好理解一点,其实它们性质一样)
private long bottomId; //这个这里没有用到,但是如果有数据层,就需要用到,这里我只是把它答应到控制台
@Autowired
private LivePressService livePressService; //定时任务运行这个方法,doTask没有被重写,所有运行父类的方法
@Override
public void start() {
try {
doTask(CoinPressConsts.CHAIN_FOR_LIVE_PRESS_DATA_URL_FORMAT);
} catch (IOException e) {
// log.error("抓取金色财经新闻异常", e);
}
} @Override
protected List<PageListPress> crawlPage(int pageNum) throws IOException {
// 最多抓取100页,多抓取也没有特别大的意思。
if (pageNum >= 100) {
return Collections.emptyList();
}
// 格式化翻页参数(第一次bottomId为0,第二次就是这次爬到的最小bottomId值)
String requestUrl = String.format(CoinPressConsts.CHAIN_FOR_LIVE_PRESS_DATA_URL_FORMAT, PAGE_SIZE, bottomId);
Response response = OkHttp.singleton().newCall(
new Request.Builder().url(requestUrl).addHeader("referer", CoinPressConsts.CHAIN_FOR_LIVE_URL).get().build())
.execute();
if (response.isRedirect()) {
// 如果请求发生了跳转,说明请求不是原来的地址了,返回空数据。
return Collections.emptyList();
} //先获得json数据格式
String responseText = response.body().string(); //在通过工具类进行数据赋值
JinSePressResult jinSepressResult = JsonUtils.objectFromJson(responseText, JinSePressResult.class);
if (null == jinSepressResult) {
// 反序列化失败
System.out.println("抓取金色财经新闻列表反序列化异常");
return Collections.emptyList();
}
// 取金色财经最小的记录id,来进行翻页
bottomId = jinSepressResult.getBottomId(); //这个是谷歌提供了guava包里的工具类,Lists这个集合工具,对list集合操作做了些优化提升。
List<PageListPress> pageListPresss = Lists.newArrayListWithExpectedSize(PAGE_SIZE); for (JinSePressResult.DayData dayData : jinSepressResult.getList()) {
JinSePressData data = dayData.getExtra();
//新闻发布时间(时间戳格式)这里可以来判断只爬多久时间以内的新闻
long createTime = data.getPublishedAt() * 1000;
Long timemill=System.currentTimeMillis();
// if (System.currentTimeMillis() - createTime > CoinPressConsts.MAX_CRAWLER_TIME) {
// // 快讯过老了,放弃
// continue;
// }
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String sd = sdf.format(new Date(createTime)); // 时间戳转换成时间
Date newsCreateTime=new Date();
try {
//获得新闻发布时间
newsCreateTime = sdf.parse(sd);
} catch (ParseException e) {
e.printStackTrace();
}
//具体文章页面路径(这里可以通过这个路径+jsoup就可以爬新闻正文所有信息了)
String href = data.getTopicUrl();
//新闻摘要
String summary = data.getSummary();
//新闻阅读数量
String pressreadcount = data.getReadNumber();
//新闻标题
String title = dayData.getTitle(); pageListPresss.add(new PageListPress(href,title, Integer.parseInt(pressreadcount),
newsCreateTime , summary));
}
return pageListPresss;
}
}

AbstractCrawlLivePressService 类

 public abstract class AbstractCrawlLivePressService {
String url;
public void doTask(String url) throws IOException {
this.url = url;
int pageNum = 1; //通过 while (true)会一直循环调取接口,直到数据为空或者时间过老跳出循环
while (true) {
List<PageListPress> newsList = crawlPage(pageNum++);
// 抓取不到新的内容本次抓取结束
if (CollectionUtils.isEmpty(newsList)) {
break;
}
//这里并没有把数据放到数据库,而是直接从控制台输出
for (int i = newsList.size() - 1; i >= 0; i--) {
PageListPress pageListNews = newsList.get(i);
System.out.println(pageListNews.toString()); }
}
}
//这个由具体实现类实现
protected abstract List<PageListPress> crawlPage(int pageNum) throws IOException; @Data
@AllArgsConstructor
@NoArgsConstructor
public static class PageListPress { //新闻详情页面url
private String href;
//新闻标题
private String title;
//新闻阅读数量
private int readCounts;
//新闻发布时间
private Date createTime;
//新闻摘要
private String summary; }
}

JinSePressResult 

/**
*在创建对象的时候一定要分析好json格式的类型
*金色新闻的返回格式就是第一层有普通属性和一个list集合
*在list集合中又有普通属性和一个extra的对象。
*/
@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class JinSePressResult { private int news;
private int count;
@JsonProperty("top_id")
private long topId;
@JsonProperty("bottom_id")
private long bottomId;
//list的名字也要和json数据的list名字一致,否则无用
private List<DayData> list; @Data
@JsonIgnoreProperties(ignoreUnknown = true)
public static class DayData { private String title;
//这里对象的属性名extra也要和json的extra名字一致
private JinSePressData extra;
@JsonProperty("topic_url")
private String topicUrl;
}
}

这里需要注意两点

   (1)在创建对象时一定要先搞清楚json格式类型是对象里含有集合,或者集合中还有对象等等。

(2) 你可以只定义你需要的属性字段,当你不能和json的属性名一致但类型不一致。比如上面你改成 List extra 这个时候序列化就会失败,因为json的extra明显是一个对象,而这边接受的确实一个集合。关键是属

性名一致 所以在赋值的时候就会报错,序列化失败。

第四步:看运行结果

这里只是截取控制台输出的部分信息,通过这种方式可以获得该网站的所有新闻信息。同时我们已经获得具体新闻的URL,那么我们就可以通过JSOup来获取该新闻的所有具体信息。(完美)

第五步:数据库去重思路

因为你不可能每一次爬取玩数据都直接放到数据库中,肯定要比较该条新闻数据库中是否已经存在,不存在才放到数据库中。思路如下:

(1)数据库表中添加一个能辨别该新闻唯一的属性字段,比如jinse+bottomId组成唯一属性,或者该新闻具体页面路径URI组成唯一属性。

(2)创建map<URL,Boolean>集合,通过URI看数据库是否存在,有就<URL,true>,没有<URL,flase>。

(3)在存储之前通过map.get(URI)如果为false则存储数据库中。

Git源码

首先说明下,源码本人是通过Idea测试运行通过,这里用了lombok,你需要现在idea或者eclipse配置Lombok。

源码地址:https://github.com/yudiandemingzi/panjiekou

想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。中校【9】

【java爬虫】---爬虫+基于接口的网络爬虫的更多相关文章

  1. 基于Thinkphp5+phpQuery 网络爬虫抓取数据接口,统一输出接口数据api

    TP5_Splider 一个基于Thinkphp5+phpQuery 网络爬虫抓取数据接口 统一输出接口数据api.适合正在学习Vue,AngularJs框架学习 开发demo,需要接口并保证接口不跨 ...

  2. 基于HttpClient实现网络爬虫~以百度新闻为例

    转载请注明出处:http://blog.csdn.net/xiaojimanman/article/details/40891791 基于HttpClient4.5实现网络爬虫请訪问这里:http:/ ...

  3. java假设模拟请求重新启动路由器(网络爬虫经常使用),还有java怎样下载图片

    我们假设在公司或家里使用网络爬虫去抓取自己索要的一些数据的时候,经常对方的站点有defence机制,会给你的http请求返回500错误,仅仅要是同样IP就请求不到数据,这时候我们仅仅能去重新启动路由器 ...

  4. android基于MVP小说网络爬虫、宝贝社区APP、仿虎扑钉钉应用、滑动阴影效果等源码

    Android精选源码 android宝贝社区app源码 android仿Tinder最漂亮的一个滑动效果 android仿滴滴打车开具发票页,ListView粘性Header Android基于MV ...

  5. 爬虫学习之基于Scrapy的网络爬虫

    ###概述 在上一篇文章<爬虫学习之一个简单的网络爬虫>中我们对爬虫的概念有了一个初步的认识,并且通过Python的一些第三方库很方便的提取了我们想要的内容,但是通常面对工作当作复杂的需求 ...

  6. 03.Python网络爬虫第一弹《Python网络爬虫相关基础概念》

    爬虫介绍 引入 之前在授课过程中,好多同学都问过我这样的一个问题:为什么要学习爬虫,学习爬虫能够为我们以后的发展带来那些好处?其实学习爬虫的原因和为我们以后发展带来的好处都是显而易见的,无论是从实际的 ...

  7. Python网络爬虫第一弹《Python网络爬虫相关基础概念》

    爬虫介绍 引入 之前在授课过程中,好多同学都问过我这样的一个问题:为什么要学习爬虫,学习爬虫能够为我们以后的发展带来那些好处?其实学习爬虫的原因和为我们以后发展带来的好处都是显而易见的,无论是从实际的 ...

  8. 03,Python网络爬虫第一弹《Python网络爬虫相关基础概念》

    爬虫介绍 引入 为什么要学习爬虫,学习爬虫能够为我们以后的发展带来那些好处?其实学习爬虫的原因和为我们以后发展带来的好处都是显而易见的,无论是从实际的应用还是从就业上. 我们都知道,当前我们所处的时代 ...

  9. 爬虫(二)Python网络爬虫相关基础概念、爬取get请求的页面数据

    什么是爬虫 爬虫就是通过编写程序模拟浏览器上网,然后让其去互联网上抓取数据的过程. 哪些语言可以实现爬虫    1.php:可以实现爬虫.php被号称是全世界最优美的语言(当然是其自己号称的,就是王婆 ...

随机推荐

  1. Archiver 3 for Mac(解压缩工具) ,想压缩解压慢一点就这么难!

    Archiver 3 for Mac是一款分割合并解压缩工具,简单实用且功能齐全,你只需简单的拖放文件就可以进行压缩,还可以设定解压密码,从而保护自己的隐私.如果文件很大你还可以切割文件.Archiv ...

  2. CICD - Teamcity 配置之一: 数据库自动部署

    数据库开发过程不是一次完成的,也是一个迭代的过程.如何快速开发和部署新的数据库对象,部署到不同的环境中,还有就是可不可以快速重建数据库对象,这里不包括数据部分. 首先从官网下载Teamcity:htt ...

  3. django自制后台左侧导航代码

    自定义一个sort.py页面: 写入一下代码: class lanmusort(object): def __init__(self): self.arr=[] def lanmuget(self,o ...

  4. centos7基于samba服务配置实例

    需求: 账号建立:产研部门所有人员,产品.开发.测试.运维: 目录建立:各二级部门分别建立以部门名称为文件夹的目录: 初步权限管理:各部门成员对本部门目录有读写权限,对其他部门目录有读权限: 建立共享 ...

  5. Ubuntu 服务器设置软件多用户访问

    假设在用户A下安装了软件xx 路径写入$home/.bashrc 这时该软件只有该用户可以使用 若要其他用户也能使用,只需要将该.bashrc拷贝到其他user的$home目录就行了

  6. 把网站打包快速在线生成ios app的正确方法

    下方的内容不用看了,请点这里 !点这里!IOS APP自助生成系统已上线,请马上去了解下: http://www.tao-jiujiu.com/post/188.html  ============= ...

  7. 在Github上为项目添加多个用户

    点击项目目录中的Settings 点击Collaborators 添加后,合作者会受到确认邮件,等待合作者确认后,合作者就可以提交了 添加组织 在Settings中找到Organizations 点击 ...

  8. 如何给网站添加IE浏览器升级提示

    1.在代码编辑器中(如Notepad++)打开网站头部模板 2.使用<!––[if IE]>语句添加升级提示,如: 判断是否IE(包含使用IE内核的浏览器) <!––[if IE]& ...

  9. STS(Spring Tool Suite)下SSM(Spring+SpringMVC+Mybatis)框架搭建(一)

    最近在用SSM框架做一个网站,就顺便把自己要做的笔记需要了解的东西都写了下来,看看对大家学习SSM框架有没有帮助. 开发环境: 1.win10 64位 2.spring-tool-suite-3.9. ...

  10. LeetCode 33 Search in Rotated Sorted Array [binary search] <c++>

    LeetCode 33 Search in Rotated Sorted Array [binary search] <c++> 给出排序好的一维无重复元素的数组,随机取一个位置断开,把前 ...