Java抓取淘宝/天猫商品详情

有项目需求抓取淘宝天猫的商品详情。琢磨一段时间搞出来了。放出来让大家参考下。

Maven依赖:
HtmlUnit

        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.5.2</version>
        </dependency>
        
        <dependency>
            <groupId>net.sourceforge.htmlunit</groupId>
            <artifactId>htmlunit</artifactId>
            <version>2.23</version>
            <exclusions>
                <exclusion>
                    <artifactId>httpclient</artifactId>
                    <groupId>org.apache.httpcomponents</groupId>
                </exclusion>
            </exclusions>
        </dependency>

准备工作:

    public static BrowserVersion getBrowserVersion() {
        BrowserVersion bv = BrowserVersion.BEST_SUPPORTED.clone();
        // 设置语言,否则不知道传过来是什么编码
        bv.setUserLanguage("zh_cn");
        bv.setSystemLanguage("zh_cn");
        bv.setBrowserLanguage("zh_cn");

        // 源码里是写死Win32的,不知道到生产环境(linux)会不会变,稳妥起见还是硬设
        bv.setPlatform("Win32");
        
        return bv;
    }
    
    public static WebClient newWebClient() {
        WebClient wc = new WebClient(bv);
        wc.getOptions().setUseInsecureSSL(true); // 允许使用不安全的SSL连接。如果不打开,站点证书过期的https将无法访问
        wc.getOptions().setJavaScriptEnabled(true); //启用JS解释器
        wc.getOptions().setCssEnabled(false); //禁用css支持
        // 禁用一些异常抛出
        wc.getOptions().setThrowExceptionOnScriptError(false);
        wc.getOptions().setThrowExceptionOnFailingStatusCode(false);

        wc.getOptions().setDoNotTrackEnabled(false); // 随请求发送DoNotTrack
        wc.setJavaScriptTimeout(1000);      // 设置JS超时,这里是1s
        wc.getOptions().setTimeout(5000); //设置连接超时时间 ,这里是5s。如果为0,则无限期等待
        wc.setAjaxController(new NicelyResynchronizingAjaxController()); // 设置ajax控制器
        
        return wc;
    }

淘宝详情抓取:
分析淘宝的页面,商品详情是异步从cdn加载的,我们只要找到这个cdn的url,直接请求获取response即可。

    public String getTaobaoDetail(String url) {
        WebClient wc = newWebClient();
        
        String detail = "";

        try {
            WebRequest request = new WebRequest(UrlUtils.toUrlUnsafe(url));
            request.setAdditionalHeaders(searchRequestHeader);

            Page page = wc.getPage(request);

            if(page.isHtmlPage()) {
                HtmlPage htmlPage = (HtmlPage) page;

                String html = htmlPage.asXml();
                               DomNodeList<HtmlElement> script = htmlPage.getHead().getElementsByTagName("script");
                String detailUrl = "";
                for(HtmlElement elm : script) {
                    String textContent = elm.getTextContent();
                    if(textContent.contains("var g_config = {")) {
                        for(String line : textContent.split("\n")) {
                            if(line.startsWith("        descUrl")) {
                                detailUrl = "http:" + RegexUtil.getFirstMatch(line,
                                        "'//dsc.taobaocdn.com/i[0-9]+/[0-9]+/[0-9]+/[0-9]+/.+[0-9]+'\\s+:"
                                ).replaceAll("\\s+:","").replace("'","");
                                break;
                            }

                        }
                        break;
                    }
                }
                if(StringUtils.isNotBlank(detailUrl))
                detail = wc.getPage(detailUrl).getWebResponse().getContentAsString().replace("var desc='","").replace("';","");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            wc.close();
        }
        return detail;
    }
        
    public static String getFirstMatch(String str,String regex) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        String ret = null;
        if(matcher.find()) {
            ret = matcher.group();
        }
        return ret;
    }

天猫详情抓取:
淘宝天猫是截然两种风格,没找到像淘宝详情页一样的cdn地址,只能从页面上去抓取了。
使用js模拟滚动,然后等待js执行完毕。至于多久真的看RP。。。

    public String getTmallDetail(String url) {
        WebClient wc = newWebClient();

        String detail = "";

        try {
            WebRequest request = new WebRequest(UrlUtils.toUrlUnsafe(url));

            request.setAdditionalHeaders(searchRequestHeader);

            wc.getCurrentWindow().getTopWindow().setOuterHeight(Integer.MAX_VALUE);
            wc.getCurrentWindow().getTopWindow().setInnerHeight(Integer.MAX_VALUE);

            Page page = wc.getPage(request);
            page.getEnclosingWindow().setOuterHeight(Integer.MAX_VALUE);
            page.getEnclosingWindow().setInnerHeight(Integer.MAX_VALUE);

            if(page.isHtmlPage()) {
                HtmlPage htmlPage = (HtmlPage) page;
                ScriptResult sr = htmlPage.executeJavaScript(String.format("javascript:window.scrollBy(0,%d);",Integer.MAX_VALUE));
                // 执行页面所有渲染相关的JS
                int left = 0;
                do {
                    left = wc.waitForBackgroundJavaScript(10);
//                    System.out.println(left);
                } while (left > 7); // 有6-7个时间超长的js任务

                htmlPage = (HtmlPage)sr.getNewPage();
                detail = htmlPage.getElementById("description").asXml()
                        .replaceAll("src=\"//.{0,100}.png\" data-ks-lazyload=", "src=");  // 移除懒加载
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            wc.close();
        }
        return detail;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值