我的编程空间,编程开发者的网络收藏夹
学习永远不晚

【Java】使用Java实现爬虫

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

【Java】使用Java实现爬虫

一、HttpClient实现模拟HTTP访问

1.1 HttpClient

HTTP 协议是 Internet 上使用得最多、最重要的协议之一,越来越多的 Java 应用程序需要直接通过 HTTP 协议来访问网络资源。虽然在 JDK 的 java net包中已经提供了访问 HTTP 协议的基本功能,但是对于大部分应用程序来说,JDK 库本身提供的功能还不够丰富和灵活。HttpClient 是 Apache Jakarta Common 下的子项目,用来提供高效的、最新的、功能丰富的支持 HTTP 协议的客户端编程工具包,并且它支持 HTTP 协议最新的版本和建议。HttpClient 已经应用在很多的项目中,比如 Apache Jakarta 上很著名的另外两个开源项目 CactusHTMLUnit 都使用了 HttpClient。Commons HttpClient项目现已终止,不再开发。 它已被Apache HttpComponents项目里的HttpClient和HttpCore模块取代,它们提供了更好的性能和更大的灵活性。

1.2 引入依赖

<dependency>    <groupId>org.apache.httpcomponentsgroupId>    <artifactId>httpclientartifactId>    <version>${httpclient.version}version>dependency><dependency>    <groupId>org.jsoupgroupId>    <artifactId>jsoupartifactId>    <version>${jsoup.version}version>dependency>

向项目中引入HttpClient和Jsoup依赖。

Jsoup用于解析获取的HTML文本,可以像JS一样通过id和class获取元素。同时Jsoup也可访问页面。

1.3 创建简单的请求操作

1.3.1 创建实例

public void testLinked() throws Exception {// 创建HttpClient对象   CloseableHttpClient httpClient = HttpClients.createDefault();   // 创建GET请求   HttpGet httpGet = new HttpGet("https://blog.csdn.net/weixin_43347659");   httpGet.setHeader("use-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36");   // 获取响应结果   CloseableHttpResponse response = httpClient.execute(httpGet);   if (response.getStatusLine().getStatusCode() == 200) {       String html = EntityUtils.toString(response.getEntity(), "UTF-8");       System.out.println(html);   }   httpClient.close();   response.close();}

HttpClient用于创建连接对象,如果请求方式为GET则可以创建HttpGet对象,若为POST请求可创建HttpPost对象,请求的参数为待访问的URL。

可以根据实际请求内容适当的增加header的内容。调用HttpClientexecute()方法发起请求,并创建一个CloseableHttpResponse响应对象,可以通过判断响应状态码确定请求的结果。

根据现在的一些防爬虫设置,可能需要在header添加固定的请求内容,例如hostorigin等内容区分人机,可根据实际情况设置。

1.3.2 Jsoup应用

@Testpublic void testJsoup() throws Exception {    // 创建HttpClient    CloseableHttpClient httpClient = HttpClients.createDefault();    // 创建GET请求    HttpGet httpGet = new HttpGet("https://www.cnblogs.com/sam-uncle/category/1469093.html");    httpGet.setHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36");    // 获取响应    CloseableHttpResponse response = httpClient.execute(httpGet);    // 获取页面内容    if (response.getStatusLine().getStatusCode() == 200) {        String html = EntityUtils.toString(response.getEntity(), "UTF-8");        // 创建Document对象        Document document = Jsoup.parse(html);        // 获取博客列表        Element blog = document.getElementsByClass("entrylist").first();        Elements blogList = blog.getElementsByClass("entrylistItem");        for (Element element : blogList) {            Elements title = element.select("a[class='entrylistItemTitle'] span");            System.out.println(title.text());        }    }    response.close();    httpClient.close();}

通过调用Jsoupparse(String html)方法即可将原始的HTML页面解析为Document类,这样我们就能够通过getElementById(String attr)getElementsByClass(String attr)select(String classAttr)等方式获取页面中的标签元素。

Document类为org.jsoup.nodes.Document注意不要使用错类。

1.4 爬取过程中可能出现的问题

1.4.1 JS异步加载问题

随着前端技术的发展,在页面中应用AJAX、VUE和AngularJS等技术已经很普及,因此在使用HttpClient时会发现,响应的结果与页面不相同,或者响应的页面并没有所需的内容。

因此可以从其他的思路来实现,例如我们可以通过访问内部接口获取响应值,通过这种方法可以跳过对页面的分析,直接获取想要的结果。主要难点在于分析该内容调用的接口。

例如我们查看CSDN的博客页面,点击搜索框可看到CSDN会推送热门的搜索信息,但是如果查看当前页面的网页源码是无法搜索到该内容的。

在这里插入图片描述

此时我们可以打开F12,查看页面的所有请求

在这里插入图片描述

此时我们可以只选择Fetch/XHR查看页面所有调用的接口,从中找到正确的接口。根据实际请求中携带参数和header的信息,编写代码。

@Testpublic void testApi() {    CloseableHttpClient httpClient = HttpClients.createDefault();    HttpGet httpGet = new HttpGet("https://silkroad.csdn.net/api/v2/assemble/list/channel/search_hot_word?new_hot_flag=1&channel_name=pc_hot_word&size=20&user_name=weixin_43347659&platform=pc&imei=10_20960811560-1623721797026-245775");    httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36");    httpGet.setHeader("Accept", "application/json, text/javascript, **");    httpPost.setHeader("Accept-Encoding", "gzip, deflate, br");    httpPost.setHeader("Accept-Language", "zh-CN,zh;q=0.9");    httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");    httpPost.setHeader("Host", "passport.csdn.net");    httpPost.setHeader("Origin", "https://passport.csdn.net");    httpPost.setHeader("Referer", "https://passport.csdn.net/login?code=applets");    // 配置登录参数    List<NameValuePair> pairList = new ArrayList<NameValuePair>();    pairList.add(new BasicNameValuePair("loginType", "1"));    pairList.add(new BasicNameValuePair("pwdOrVerifyCode", "password"));    pairList.add(new BasicNameValuePair("uaToken", ""));    pairList.add(new BasicNameValuePair("userIdentification", "username"));    pairList.add(new BasicNameValuePair("webUmidToken", ""));    httpPost.setEntity(new UrlEncodedFormEntity(pairList, HTTP.UTF_8));    CloseableHttpResponse response = httpClient.execute(httpPost);    if (response.getStatusLine().getStatusCode() == 200) {        System.out.println("登录成功");        // 这里要注销请求,否则会影响后续的请求        httpPost.abort();        HttpGet httpGet = new HttpGet("https://mall.csdn.net/myorder?spm=1001.2014.3001.5137");        httpGet.setHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36");        CloseableHttpResponse response1 = httpClient.execute(httpGet);        if (response1.getStatusLine().getStatusCode() == 200) {            System.out.println("==============================开始打印页面==============================");            System.out.println(EntityUtils.toString(response1.getEntity()));            System.out.println("==============================结束打印页面==============================");        }        response1.close();    }    response.close();    httpClient.close();}

该案例为失败案例,由于登录方式多变,可能出现的验证码等人机校验,导致用户登录的难度加大,例如上述案例,直接访问登录接口后,会直接重定向到人机验证界面,导致无法正常登录。有些页面也存在在前端进行密码加密,导致无法获取正确的密码。

因此上述例子只是提供一个思路。

二、HtmlUtil实现JS异步加载页面

2.1 HtmlUtil

htmlunit 是一款开源的java 页面分析工具,读取页面后,可以有效的使用htmlunit分析页面上的内容。项目可以模拟浏览器运行,被誉为java浏览器的开源实现。是一个没有界面的浏览器,运行速度迅速。是junit的扩展之一。

2.2 引入依赖

<dependency><groupId>net.sourceforge.htmlunitgroupId><artifactId>htmlunitartifactId><version>${htmlutil.version}version>dependency>

2.3 创建简单的请求操作

2.3.1 创建实例

@Testpublic void testLinked() {    try (WebClient webClient = new WebClient(BrowserVersion.CHROME)) {        webClient.getOptions().setThrowExceptionOnScriptError(false);//当JS执行出错的时候是否抛出异常        webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//当HTTP的状态非200时是否抛出异常        webClient.getOptions().setActiveXNative(false);        webClient.getOptions().setCssEnabled(false);//是否启用CSS        webClient.getOptions().setJavaScriptEnabled(true); //很重要,启用JS        webClient.setAjaxController(new NicelyResynchronizingAjaxController());//很重要,设置支持AJAX        //开始请求网站        HtmlPage loginPage = webClient.getPage("https://ent.sina.com.cn/film/");        webClient.waitForBackgroundJavaScript(30000);//该方法阻塞线程        System.out.println("=================开始打印页面=================");        System.out.println(loginPage.asXml());        System.out.println("=================结束打印页面=================");    } catch (Exception e) {        e.printStackTrace();    }}

对webClient的配置很重要,尤其是setAjaxController()方法,使得模拟页面可以支持AJAX异步加载。

对于Vue和AngularJS渲染的页面HtmlUtil在其处理上也不是太好,加载JS也只能加载原始页面中包含的内容,

2.3.2 模拟浏览器操作

HtmlUtil可以创建一个无界面的浏览器,所以可以通过代码对文本框赋值和进行点击操作,完成一些简单的操作。示例:

@Testpublic void testSearch() {    WebClient webClient = new WebClient(BrowserVersion.CHROME);    // 设置当前的AJAX控制器    webClient.setAjaxController(new NicelyResynchronizingAjaxController());    // 设置CSS支持    webClient.getOptions().setCssEnabled(false);    // 设置JavaScript是否启用    webClient.getOptions().setJavaScriptEnabled(true);    // 设置ActiveX是否启用    webClient.getOptions().setActiveXNative(false);    // 设置访问错误时是否抛出异常    webClient.getOptions().setThrowExceptionOnFailingStatusCode(true);    // 设置JS报错时是否抛出异常    webClient.getOptions().setThrowExceptionOnScriptError(false);    try {        HtmlPage htmlPage = webClient.getPage("https://www.csdn.net/");        // 阻塞当前线程,直到指定时间后结束        webClient.waitForBackgroundJavaScript(10*1000);        // 获取搜索框        HtmlInput search = (HtmlInput) htmlPage.getByXPath("//*[@id=\"toolbar-search-input\"]").get(0);        search.setAttribute("value", "HtmlUtil用法");        // 点击搜索        HtmlButton button = (HtmlButton) htmlPage.getByXPath("//*[@id=\"toolbar-search-button\"]").get(0);        HtmlPage newHtmlPage = button.click();        System.out.println("=============打印页面=============");        System.out.println(newHtmlPage.asXml());        System.out.println("=============打印页面=============");    } catch (IOException e) {    e.printStackTrace();    }}

该示例通过访问CSDN的首页,为搜索框赋值,操作点击后可获取搜索结果。

由于CSDN的搜索结果是通过Vue框架加载,所以无法获取到最终的结果。

2.4 爬取待登录的页面

操作与2.3.2节类似,主要思路为获取登录页面,为表单元素添加用户名和密码,再通过click()方法点击登录按钮,提交表单,登录成功后会自动将cookie存放在WebClient中,可通过WebClient再次访问其他需要登录的页面。

相较于HttpClient,HtmlUtil可以直接操作页面比访问接口相对容易,但是针对于Vue框架和需要验证码登录的页面还是存在问题。


参考资料:

HtmlUnit 官网

HtmlUtil API文档

HttpClient 官网

HttpClient API文档

来源地址:https://blog.csdn.net/weixin_43347659/article/details/126162900

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

【Java】使用Java实现爬虫

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

【Java】使用Java实现爬虫

文章目录 使用Java实现爬虫一、HttpClient实现模拟HTTP访问1.1 HttpClient1.2 引入依赖1.3 创建简单的请求操作1.3.1 创建实例1.3.2 Jsoup应用 1.4 爬取过程中可能出现的问题
2023-08-24

在Java中使用Jsoup实现一个爬虫功能

在Java中使用Jsoup实现一个爬虫功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。 Java 爬虫工具Jsoup详解Jsoup是一款 Java 的 HTML 解析器,可直
2023-05-31

Java语言怎么实现爬虫

这篇文章给大家分享的是有关Java语言怎么实现爬虫的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。为什么我们要爬取数据在大数据时代,我们要获取更多数据,就要进行数据的挖掘、分析、筛选,比如当我们做一个项目的时候,需
2023-06-22

利用JAVA实现一个多线程爬虫

利用JAVA实现一个多线程爬虫?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。JAVA 多线程爬虫实例详解前言以前喜欢Python的爬虫是出于他的简洁,但到了后期
2023-05-31

如何使用Java爬虫批量爬取图片

这篇文章主要介绍了如何使用Java爬虫批量爬取图片,对于爬虫的入门来说,图片相对来说是比较容易获取的,因为大部分图片都不是敏感数据,所以不会遇到什么反爬措施,对于入门爬虫来说是比较合适的,需要的朋友可以参考下
2023-05-15

怎么使用Java爬虫批量爬取图片

本篇内容主要讲解“怎么使用Java爬虫批量爬取图片”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么使用Java爬虫批量爬取图片”吧!爬取思路对于这种图片的获取,其实本质上就是就是文件的下载(H
2023-07-06

Java中怎么实现一个网络爬虫

Java中怎么实现一个网络爬虫,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。首先介绍每个类的功能:DownloadPage.java的功能是下载此超链接的页面源代码.Fun
2023-06-17

怎么在hadoop中实现一个java爬虫

今天就跟大家聊聊有关怎么在hadoop中实现一个java爬虫,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。需要用到Cygwin:一个在windows平台上运行的类UNIX模拟环境,直
2023-05-31

java如何写爬虫

这篇文章主要介绍了java如何写爬虫,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3.
2023-06-14

利用java怎么实现一个网页爬虫功能

利用java怎么实现一个网页爬虫功能?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。爬虫实现原理网络爬虫基本技术处理网络爬虫是数据采集的一种方法,实际项目开发中,通过爬虫做数
2023-05-31

Java HttpClient爬虫请求

**本项目采用spring-boot构建, maven工程 添加依赖 pom文件 4.0.0 org.test testDome 0.0.1-SNAPSHOT org.apache.httpcomponents htt
2023-08-17

如何实现Java手撸网络爬虫框架

这篇文章主要为大家展示了“如何实现Java手撸网络爬虫框架”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“如何实现Java手撸网络爬虫框架”这篇文章吧。首先介绍每个类的功能:DownloadPag
2023-06-20

C#如何使用selenium实现爬虫

本文小编为大家详细介绍“C#如何使用selenium实现爬虫”,内容详细,步骤清晰,细节处理妥当,希望这篇“C#如何使用selenium实现爬虫”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、介绍:Seleni
2023-07-02

Java爬虫爬取漫画示例

这篇文章主要介绍了Java爬虫爬取漫画示例,大部分的爬虫入门教学都是爬取图片的,本文就来测试一下爬取网站的漫画,需要的朋友可以参考下
2023-05-18

java 爬虫详解及简单实例

Java爬虫一、代码爬虫的实质就是打开网页源代码进行匹配查找,然后获取查找到的结果。打开网页:URL url = new URL(http://www.cnblogs.com/Renyi-Fan/p/6896901.html);
2023-05-31

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录