前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Jsoup+Htmlunit抓取图片遇到坑

Jsoup+Htmlunit抓取图片遇到坑

作者头像
赵哥窟
发布2019-07-14 07:05:28
2.6K0
发布2019-07-14 07:05:28
举报
文章被收录于专栏:日常技术分享
Jsoup简介

Jsoup是用于解析HTML,就类似XML解析器用于解析XML。 Jsoup它解析HTML成为真实世界的HTML。

能用Jsoup实现什么? ●从URL,文件或字符串中刮取并解析HTML ●查找和提取数据,使用DOM遍历或CSS选择器 ●操纵HTML元素,属性和文本 ●根据安全的白名单清理用户提交的内容,以防止XSS攻击 ●输出整洁的HTML

安装

代码语言:javascript
复制
<dependency>
       <groupId>org.jsoup</groupId>
       <artifactId>jsoup</artifactId>
       <version>1.12.1</version>
  </dependency>        
Htmluiit简介

htmlunit 是一款开源的java 页面分析工具,优点就是得到js执行后的值。用于抓取动态页面。

安装

代码语言:javascript
复制
<dependency>
        <groupId>net.sourceforge.htmlunit</groupId>
        <artifactId>htmlunit</artifactId>
         <version>2.35.0</version>
</dependency>
使用Jsoup+Htmlunit
代码语言:javascript
复制
public String getHtmlPageResponse(String url) throws Exception {

        //请求超时时间,默认20秒
        int timeout = 20000;
        //等待异步JS执行时间,默认20秒
        int waitForBackgroundJavaScript = 20000;
        String result = "";

        final 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

        webClient.getOptions().setTimeout(timeout);//设置“浏览器”的请求超时时间
        webClient.setJavaScriptTimeout(timeout);//设置JS执行的超时时间

        HtmlPage page;
        try {
            page = webClient.getPage(url);
        } catch (Exception e) {
            webClient.close();
            throw e;
        }
        webClient.waitForBackgroundJavaScript(waitForBackgroundJavaScript);//该方法阻塞线程

        result = page.asXml();
        webClient.close();

        return result;
    }

下载网页中我们想要的图片

代码语言:javascript
复制
public void  getHtmlContent(String url){
        // 发起请求
        String content = null;
        try {
            content = getHtmlPageResponse(url);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 解析网页 得到文档对象
        Document doc = Jsoup.parse(content);
        // 获取指定的 <img />
        Elements elements = doc.select("img[src$=.png]");
        List<String> picList = new ArrayList<>();
        for (Element element :elements){
            // 获取 <img /> 的 src
            String imageUrl = element.attr("src");
            // 取到我们想要的图片
            if (imageUrl.contains(WEATHER_PIC_BASE_URL)) {
                picList.add(imageUrl);
            }
        }

        // 获取文件夹下所有文件名
        List<String> fileNameList = getFileList(savePath);
        for(String imgUrl:picList){
            String fileName = getFileNameWihtUrl(imgUrl);
            // 图片是否存在
            boolean isPic = fileNameList.contains(fileName);
            if (!isPic) {
                 // 下载图片
            }
        }

    }

保存图片到本地

代码语言:javascript
复制
public void downloadImages(String url, String fileName,String savePath,String imageFormat,Integer headerType) {
        // 创建httpclient实例
        CloseableHttpClient httpclient = HttpClients.createDefault();

        // Http请求
        try {
            HttpGet httpGet = new HttpGet(url);
            CloseableHttpResponse pictureResponse = httpclient.execute(httpGet);
            HttpEntity pictureEntity = pictureResponse.getEntity();
            InputStream inputStream = pictureEntity.getContent();

            // 使用 common-io 下载图片到本地,注意图片名不能重复 
            FileUtils.copyToFile(inputStream, new File( savePath+ fileName + imageFormat));
            pictureResponse.close(); // pictureResponse关闭

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

下载图片安装commons-io

代码语言:javascript
复制
<dependency>
         <groupId>commons-io</groupId>
         <artifactId>commons-io</artifactId>
         <version>2.6</version>
</dependency>

对于一般的网站来说。到这里能够爬取数据了,但是今天遇到一个问题,我获取了网页上所有JS执行后的动态图片链接,但是下载到本地图片损坏打不开。调试,把抓取的图片地址复制到浏览器中显示链接无效。what??

打开网页调试工具,

屏幕快照 2019-07-11 15.27.18.png

复制Request URL重新打开一个页面一样的显示链接无效。

猜想

网页调试工具Network调试,抓取的图片双击无数次都有显示图片,但是把 Request URL复制到一个新页面就显示无效。猜想应该是访问页面的时候返回了Cookie,下载图片的时候也要把Cookie带回去验证。

查看下载需要哪些Cookie。然后在downloadImages类中增加

代码语言:javascript
复制
// 创建httpclient实例
CloseableHttpClient httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader("Cache-Control", "no-cache");

增加之后就可以下载成功了。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.07.11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Jsoup简介
  • Htmluiit简介
  • 使用Jsoup+Htmlunit
    • 猜想
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档