最近做的爬虫一些事
最近做的爬虫一些事
标签(空格分隔): 杂乱之地
最近在做爬虫,主要是抓取淘宝商品的销量数据。在搜索页很容易就能抓到细览页的数据,主要问题难点是在抓取细览页中,页面的销量及评价数据是通过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支持的问题。