• 最近做的爬虫一些事


    最近做的爬虫一些事

    标签(空格分隔): 杂乱之地


    最近在做爬虫,主要是抓取淘宝商品的销量数据。在搜索页很容易就能抓到细览页的数据,主要问题难点是在抓取细览页中,页面的销量及评价数据是通过ajax来动态加载的。这一部分处理比较麻烦。同时又要解决屏蔽的问题。这几天一直在找解决访问。一般的爬虫都是不支持ajax数据的爬取的。写一下这几天做的各种工具的demo吧。
    现在(2016年1月)市面上能够抓取ajax数据的主要有以下技术:htmlunit,casperjs,phantomjs,selenium.

    htmlunit

    • 代码
    package com.kis;
    
    import com.gargoylesoftware.htmlunit.*;
    import com.gargoylesoftware.htmlunit.html.*;
    
    import java.io.IOException;
    import java.net.URL;
    import java.util.Properties;
    
    /**
     * Created by wanglong on 16-1-21.
     */
    public class TestProxy {
        public static void main(String[] args) throws IOException {
            String url = "https://item.taobao.com/item.htm?id=520081147502&ns=1&abbucket=11#detail";
            WebClient webClient = new WebClient(BrowserVersion.FIREFOX_38);//设置浏览器的User-Agent
            webClient.setJavaScriptTimeout(100000);//设置JS执行的超时时间
            webClient.getOptions().setThrowExceptionOnScriptError(false);//当JS执行出错的时候是否抛出异常
            webClient.getOptions().setRedirectEnabled(true);
            webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);//当HTTP的状态非200时是否抛出异常
            webClient.getOptions().setTimeout(30000);//设置“浏览器”的请求超时时间
            webClient.getOptions().setCssEnabled(false);//是否启用CSS
            webClient.getOptions().setJavaScriptEnabled(true); //很重要,启用JS
            webClient.waitForBackgroundJavaScript(100000);//设置JS后台等待执行时间
            webClient.getOptions().setThrowExceptionOnScriptError(false);
            webClient.setAjaxController(new NicelyResynchronizingAjaxController());//设置支持AJAX
            HtmlPage resultPage = webClient.getPage(url);
            HtmlStrong strong;
            webClient.waitForBackgroundJavaScript(2000);
            Long start = System.currentTimeMillis();
            for (int i = 0; i < 20; i++) {
                strong = resultPage.getFirstByXPath("//*[@id="J_SellCounter"]");
                if (strong.asText().equals("-")) {
                    webClient.waitForBackgroundJavaScript(1000);
                } else {
                    Long end = System.currentTimeMillis();
                    System.out.println(strong.asText());
                    System.out.print("  所用时间为" + (end - start) / 1000 + "秒");
                    break;
                }
            }
        }
    }
    
    
    • 通过htmlunit可以获得到销量数据。但是由于要解决屏蔽及效率问题(多线程),所以肯定要使用代理的,但是我机器上设置代理不起作用不知道为什么,所以放弃了使用htmlunit
            Properties prop = System.getProperties();
            prop.setProperty("proxySet", "true");
            prop.setProperty("http.proxyHost", "61.191.27.117");
            prop.setProperty("http.proxyPort", "443");
    
            WebRequest webRequest = new WebRequest(new URL(url));
            webRequest.setProxyHost("202.103.241.169");
            webRequest.setProxyPort(1080);
            webRequest.setSocksProxy(true);
    
    • 通过以上两种方式设置的代理都不管用,通过访问www.ip138.com获得的ip还是我本机的ip,所以就放弃了这种方法。

    js

    • casperjs&phantomjs
      这两个都是js的自动测试框架。通过js来模拟点击浏览器操作,属于无界面的浏览器。通过实验发现也是可以并且很轻松的能够获得通过ajax加载的数据。但是只能通过shell命令来输入代理。所以这种方式最后也是放弃了。
    • selenium
      selenium也是一个自动测试框架,属于有界面的,原理与上面的js是一样的。通过命令来确定发送操作浏览器的指令。经过一翻实验发现,对于代理的操作相对来说也不是很方便,而且属于有界面的,还不如使用chrome来开发插件的方式来解决这个问题。也方便非it人员调用。

    总结:
    1.如果需要频繁抓取,目前的解决方案是chrome+插件来解决。
    2.如果能解决htmlunit的代理问题。效果优于1.
    3.htmlunit代理问题不局限于代理不上,还有对于socks支持的问题。

  • 相关阅读:
    Button 样式设置
    WPF 运行报错:在使用 ItemsSource 之前,项集合必须为空。
    c# List 按条件查找、删除
    c# WPF DataGrid设置一列自增一
    C# WPF DataGrid去掉最左侧自动生成一列
    int 转换成定长的 byte数组
    字节数组 byte[] 与 int型数字的相互转换
    [ c# ] int 类型转换为固定长度的字符串
    ListView 绑定 字典
    不能引用的文件,却需要在程序底层使用的文件 的存放位置
  • 原文地址:https://www.cnblogs.com/-10086/p/5171269.html
Copyright © 2020-2023  润新知