博客搬家系列(五)

您所在的位置:网站首页 中国博客网 博客搬家系列(五)

博客搬家系列(五)

2023-07-28 14:13| 来源: 网络整理| 查看: 265

博客搬家系列(五)-爬取开源中国博客

一.前情回顾 

 博客搬家系列(一)-简介:https://blog.csdn.net/rico_zhou/article/details/83619152

 博客搬家系列(二)-爬取CSDN博客:https://blog.csdn.net/rico_zhou/article/details/83619509

 博客搬家系列(三)-爬取博客园博客:https://blog.csdn.net/rico_zhou/article/details/83619525

 博客搬家系列(四)-爬取简书文章:https://blog.csdn.net/rico_zhou/article/details/83619538

 博客搬家系列(六)-爬取今日头条文章:https://blog.csdn.net/rico_zhou/article/details/83619564

 博客搬家系列(七)-本地WORD文档转HTML:https://blog.csdn.net/rico_zhou/article/details/83619573

 博客搬家系列(八)-总结:https://blog.csdn.net/rico_zhou/article/details/83619599

二.开干(获取文章URL集合) 

爬取开源中国的博客思路跟CSDN一样,同样,我们找一个文章比较多的主页为例分析源码,如https://my.oschina.net/u/222608

u后面的字符串即为博主id,同简书相像,经我们下拉发现,列表加载方式也是下拉自动加载,即滚动条到达一定程度时则js去请求后台,那么我们按下F12或者右击审查元素,点击network查看一下详情

此时我们缓慢滚动鼠标让其继续加载文章列表,我们发现多了一条请求widgets/_space_index_newest_blog?catalogId=0&q=&p=2&type=ajax

经测试发现p=2即表示页数,将url输入浏览器,发现页面没有了样式,但是没关系,文章的url还都在,我们只需要文章url

同样,右击查看源码,寻找url,并代码获取url

代码如下:

/** * @date Oct 17, 2018 12:30:46 PM * @Desc * @param blogMove * @param oneUrl * @return * @throws IOException * @throws MalformedURLException * @throws FailingHttpStatusCodeException */ public void getOsChinaArticleUrlList(Blogmove blogMove, String oneUrl, List urlList) throws FailingHttpStatusCodeException, MalformedURLException, IOException { // 模拟浏览器操作 // 创建WebClient WebClient webClient = new WebClient(BrowserVersion.CHROME); // 关闭css代码功能 webClient.getOptions().setThrowExceptionOnScriptError(false); webClient.getOptions().setCssEnabled(false); // 如若有可能找不到文件js则加上这句代码 webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); // 获取第一级网页html HtmlPage page = webClient.getPage(oneUrl); // System.out.println(page.asXml()); Document doc = Jsoup.parse(page.asXml()); Element pageMsg22 = doc.select("div.list-container.space-list-container").first(); if (pageMsg22 == null) { return; } Elements pageMsg = pageMsg22.select("div.content"); Element linkNode; for (Element e : pageMsg) { linkNode = e.select("a.header").first(); if (linkNode == null) { continue; } if (urlList.size() < blogMove.getMoveNum()) { urlList.add(linkNode.attr("href")); } else { break; } } return; }

url集合获取如下

三.开干(获取文章具体信息)

接下来根据具体的url去获取文章详情,同样,我们还是打开一篇博文,以使用爬虫框架htmlunit整合springboot出现的一个不兼容问题为例,使用Chrome打开,我们可以看到一些基本信息,如文章的类型为原创,标题,时间,作者,阅读数,文章文字信息,图片信息等

这里也需要特别注意一下的就是时间的获取,同简书文章时间显示并不是唯一,他会将时间进行一些改变显示,这里需要注意一下,将获取的时间反向解析一下,这里不再过多讲述。

同样,右击查看源码找到对应的元素,然后获取内容

代码如下:

/** * @date Oct 17, 2018 12:46:52 PM * @Desc 获取详细信息 * @param blogMove * @param url * @return * @throws IOException * @throws MalformedURLException * @throws FailingHttpStatusCodeException */ public Blogcontent getOsChinaArticleMsg(Blogmove blogMove, String url, List bList) throws FailingHttpStatusCodeException, MalformedURLException, IOException { Blogcontent blogcontent = new Blogcontent(); blogcontent.setArticleSource(blogMove.getMoveWebsiteId()); // 模拟浏览器操作 // 创建WebClient WebClient webClient = new WebClient(BrowserVersion.CHROME); // 关闭css代码功能 webClient.getOptions().setThrowExceptionOnScriptError(false); webClient.getOptions().setCssEnabled(false); // 如若有可能找不到文件js则加上这句代码 webClient.getOptions().setThrowExceptionOnFailingStatusCode(false); // 获取第一级网页html HtmlPage page = webClient.getPage(url); Document doc = Jsoup.parse(page.asXml()); // 获取标题 String title = BlogMoveOsChinaUtils.getOsChinaArticleTitle(doc); // 是否重复去掉 if (blogMove.getMoveRemoveRepeat() == 0) { // 判断是否重复 if (BlogMoveCommonUtils.articleRepeat(bList, title)) { return null; } } blogcontent.setTitle(title); // 获取作者 blogcontent.setAuthor(BlogMoveOsChinaUtils.getOsChinaArticleAuthor(doc)); // 获取时间 if (blogMove.getMoveUseOriginalTime() == 0) { blogcontent.setGtmCreate(BlogMoveOsChinaUtils.getOsChinaArticleTime(doc)); } else { blogcontent.setGtmCreate(new Date()); } blogcontent.setGtmModified(new Date()); // 获取类型 blogcontent.setType(BlogMoveOsChinaUtils.getOsChinaArticleType(doc)); // 获取正文 blogcontent.setContent(BlogMoveOsChinaUtils.getOsChinaArticleContent(doc, blogMove, blogcontent)); // 设置其他 blogcontent.setStatus(blogMove.getMoveBlogStatus()); blogcontent.setBlogColumnName(blogMove.getMoveColumn()); // 特殊处理 blogcontent.setArticleEditor(blogMove.getMoveArticleEditor()); blogcontent.setShowId(DateUtils.format(new Date(), DateUtils.YYYYMMDDHHMMSSSSS)); blogcontent.setAllowComment(0); blogcontent.setAllowPing(0); blogcontent.setAllowDownload(0); blogcontent.setShowIntroduction(1); blogcontent.setIntroduction(""); blogcontent.setPrivateArticle(1); return blogcontent; }

详细信息

/** * @date Oct 17, 2018 1:10:19 PM * @Desc 获取标题 * @param doc * @return */ public static String getOsChinaArticleTitle(Document doc) { // 标题 Element pageMsg2 = doc.select("div.article-detail").first().select("h1.header").first(); return pageMsg2.ownText(); } /** * @date Oct 17, 2018 1:10:28 PM * @Desc 获取作者 * @param doc * @return */ public static String getOsChinaArticleAuthor(Document doc) { Element pageMsg2 = doc.select("div.article-detail").first().select("a.__user").first().select("span").first(); return pageMsg2.html(); } /** * @date Oct 17, 2018 1:10:33 PM * @Desc 获取时间 * @param doc * @return */ public static Date getOsChinaArticleTime(Document doc) { Element pageMsg2 = doc.select("div.article-detail").first().select("div.item").first(); String date = pageMsg2.ownText().trim(); if (date.startsWith("发布于")) { date = date.substring(date.indexOf("发布于") + 3).trim(); } if (date.indexOf(CommonSymbolicConstant.FORWARD_SLASH) < 4) { date = DateUtils.format(new Date(), DateUtils.YYYY) + CommonSymbolicConstant.FORWARD_SLASH + date; } // 这地方时间格式变化太多暂时不实现 Date d = DateUtils.formatStringDate(date, DateUtils.YYYY_MM_DD_HH_MM_SS3); // 注意有些格式不正确 return d == null ? new Date() : d; } /** * @date Oct 17, 2018 1:10:37 PM * @Desc 获取类型 * @param doc * @return */ public static String getOsChinaArticleType(Document doc) { Element pageMsg2 = doc.select("div.article-detail").first().select("h1.header").first().select("div.horizontal") .first(); if ("原".equals(pageMsg2.html())) { return "原创"; } else if ("转".equals(pageMsg2.html())) { return "转载"; } else if ("译".equals(pageMsg2.html())) { return "翻译"; } return "原创"; }

正文

/** * @date Oct 17, 2018 1:10:41 PM * @Desc 获取正文 * @param doc * @param object * @param blogcontent * @return */ public static String getOsChinaArticleContent(Document doc, Blogmove blogMove, Blogcontent blogcontent) { Element pageMsg2 = doc.select("div.content#articleContent").first(); // 为了图片显示正常去掉一个元素 pageMsg2.select("div.ad-wrap").remove(); String content = pageMsg2.toString(); String images; // 注意是否需要替换图片 if (blogMove.getMoveSaveImg() == 0) { // 保存图片到本地 // 先获取所有图片连接,再按照每个链接下载图片,最后替换原有链接 // 先创建一个文件夹 // 先创建一个临时文件夹 String blogFileName = String.valueOf(UUID.randomUUID()); FileUtils.createFolder(FilePathConfig.getUploadBlogPath() + File.separator + blogFileName); blogcontent.setBlogFileName(blogFileName); // 匹配出所有链接 List imgList = BlogMoveCommonUtils.getArticleImgList(content); // 下载并返回重新生成的imgurllist List newImgList = getOsChinaArticleNewImgList(blogMove, imgList, blogFileName); // 拼接文章所有链接 images = BlogMoveCommonUtils.getArticleImages(newImgList); blogcontent.setImages(images); // 替换所有链接按顺序 content = getOsChinaNewArticleContent(content, imgList, newImgList); } return content; }

这里需要注意的一点是,当我爬取文章后,发现图片的排版和文字重合了,并且只要有图片就会重合,大概是开源中国的博客样式不同导致,只需去掉标签div.ad-wrap即可

// 为了图片显示正常去掉一个元素 pageMsg2.select("div.ad-wrap").remove();

最后获取的正文

本人网站效果图:

欢迎交流学习!

完整源码请见github:https://github.com/ricozhou/blogmove​​​​​​​



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3