c httpclient抓取网页(一下和网页采集相关的组件和插件有什么区别?)

优采云 发布时间: 2021-10-19 06:04

  c httpclient抓取网页(一下和网页采集相关的组件和插件有什么区别?)

  其实很多做Java编程的人都不懂SEO,不知道怎么去百度收录等。当然,不是所有程序员都考虑爬网和网页爬虫,但是他们是专门针对这个人的. ,还是需要了解一下里面的知识,接下来介绍一些爬虫和网页采集相关的组件和插件~

  大家在做爬虫、网页采集、通过网页自动写数据的时候基本都接触过这两个组件。网上已经有很多介绍资料了。我想从实际应用开始,从一个角度谈谈我对这两个组件的看法,并将它们记录在博客中,以便我以后阅读。欢迎大家批评指正。

  本文主要比较两者的优缺点并介绍应用中的使用技巧,推荐一些入门资料和非常实用的辅助工具,希望对大家有所帮助。

  如果您有任何问题或建议,您可以给我留言,共同交流和学习。

  我们先来看看这两个组件的区别和优缺点:

  单位

  HtmlUnit 最初是一个自动化测试工具。它结合使用HttpClient和java自带的网络api来实现。它和HttpClient的区别在于它比HttpClient更“人性化”。

  写HtmlUnit代码的时候,好像是在操作浏览器而不是写代码获取页面(getPage)-找到文本框(getElementByID || getElementByName || getElementByXPath等)-输入文本(type, setValue, setText,等)——其他一些类似的操作——找到提交按钮——提交——得到一个新的Page,这样就很像后台有人帮你操作浏览器了,你只要告诉他怎么操作要操作,需要填写哪些值。

  一、网页模拟

  首先,让我谈谈 HtmlUnit 相对于 HttpClient 最明显的好处之一。HtmlUnit 更好地将网页封装成一个对象。如果非要说HttpClient返回的接口HttpResponse其实存储的是一个对象,那很好,但是HtmlUnit不仅保存了网页对象,更难能可贵的是它还存储了网页的所有基本操作甚至事件. 也就是说,我们可以像在jsp中写js一样操作这个网页,非常方便,比如:你要一个节点的上一个节点,找到所有的按钮,找到“bt-style”的样式为所有元素,先修改一些元素,再转成String,或者我直接拿到这个网页然后操作这个网页,很方便的完成一个提交。这意味着如果你想分析一个网页,那将是非常容易的。比如我附上一段百度新闻高级搜索的代码:

  // 得到浏览器对象,直接New一个就能得到,现在就好比说你得到了一个浏览器了

WebClient webclient = new WebClient();

// 这里是配置一下不加载css和javaScript,配置起来很简单,是不是

webclient.getOptions().setCssEnabled(false);

webclient.getOptions().setJavaScriptEnabled(false);

// 做的第一件事,去拿到这个网页,只需要调用getPage这个方法即可

HtmlPage htmlpage = webclient.getPage("http://news.baidu.com/advanced_news.html");

// 根据名字得到一个表单,查看上面这个网页的源代码可以发现表单的名字叫"f”

final HtmlForm form = htmlpage.getFormByName("f");

// 同样道理,获取”百度一下“这个按钮

final HtmlSubmitInput button = form.getInputByValue("百度一下");

// 得到搜索框

final HtmlTextInput textField = form.getInputByName("q1");

// 最近周星驰比较火呀,我这里设置一下在搜索框内填入"周星驰"

textField.setValueAttribute("周星驰");

// 输入好了,我们点一下这个按钮

final HtmlPage nextPage = button.click();

// 我把结果转成String

String result = nextPage.asXml();

System.out.println(result);

  然后就可以将结果结果复制到一个文本中,然后用浏览器打开该文本。是你想要的吗(见图)?这很简单,对吧?为什么感觉简单,因为完全符合我们的操作和浏览,当然最后也是通过HttpClient等一些工具类来实现的,但是封装的非常人性化,很神奇。

  Htmlunit可以有效的分析dom标签,可以有效的在页面上运行js,得到一些需要执行js的值。您需要做的就是执行 executeJavaScript() 方法。这些都是HtmlUnit为我们封装的。好吧,我们所要做的就是告诉它需要做什么。

  WebClient webclient = new WebClient();

HtmlPage htmlpage = webclient.getPage("you url");

htmlpage.executeJavaScript("the function name you want to execute");

  对于使用Java的程序员来说,对象的操作再熟悉不过了,HtmlUnit所做的就是帮助我们把网页封装成一个对象,一个功能丰富的透明对象。

  二、自动处理网络响应

  HtmlUnit有强大的响应处理机制,我们知道:常见的404是资源未找到,100是继续,300是跳转……当我们使用HttpClient时,它会告诉我们响应结果,当然你可以做自己判断,比如当你发现响应码是302时,会在响应头中找到新地址,自动跳过。当您发现它是 100 时,您将发送另一个请求。如果你使用HttpClient,你可以做这个来做,也可以写的更完整,但是HtmlUnit把这个​​功能实现的更完整,甚至说还包括页面JS的自动跳转(响应码是200,但是响应页面是一个JS),天涯的登录就是这样的情况,一起来看看吧。

  /**

* @author CaiBo

* @date 2014年9月15日 上午9:16:36

* @version $Id$

*

*/

public class TianyaTest {

public static void main(String[] args) throws Exception {

// 这是一个测试,也是为了让大家看的更清楚,请暂时抛开代码规范性,不要纠结于我多建了一个局部变量等

// 得到认证https的浏览器对象

HttpClient client = getSSLInsecureClient();

// 得到我们需要的post流

HttpPost post = getPost();

// 使用我们的浏览器去执行这个流,得到我们的结果

HttpResponse hr = client.execute(post);

// 在控制台输出我们想要的一些信息

showResponseInfo(hr);

}

private static void showResponseInfo(HttpResponse hr) throws ParseException, IOException {

System.out.println("响应状态行信息:" + hr.getStatusLine());

System.out.println("—————————————————————");

System.out.println("响应头信息:");

Header[] allHeaders = hr.getAllHeaders();

for (int i = 0; i < allHeaders.length; i++) {

System.out.println(allHeaders[i].getName() + ":" + allHeaders[i].getValue());

}

System.out.println("—————————————————————");

System.out.println("响应正文:");

System.out.println(EntityUtils.toString(hr.getEntity()));

}

// 得到一个认证https链接的HttpClient对象(因为我们将要的天涯登录是Https的)

// 具体是如何工作的我们后面会提到的

private static HttpClient getSSLInsecureClient() throws Exception {

// 建立一个认证上下文,认可所有安全链接,当然,这是因为我们仅仅是测试,实际中认可所有安全链接是危险的

SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null,

new TrustStrategy() {

public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {

return true;

}

}).build();

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext);

return HttpClients.custom().setSSLSocketFactory(sslsf)//

// .setProxy(new HttpHost("127.0.0.1", 8888))

.build();

}

// 获取我们需要的Post流,如果你是把我的代码复制过去,请记得更改为你的用户名和密码

private static HttpPost getPost() {

HttpPost post = new HttpPost("https://passport.tianya.cn/login");

// 首先我们初始化请求头

post.addHeader("Referer", "https://passport.tianya.cn/login.jsp");

post.addHeader("Host", "passport.tianya.cn");

post.addHeader("Origin", "http://passport.tianya.cn");

// 然后我们填入我们想要传递的表单参数(主要也就是传递我们的用户名和密码)

// 我们可以先建立一个List,之后通过post.setEntity方法传入即可

// 写在一起主要是为了大家看起来方便,大家在正式使用的当然是要分开处理,优化代码结构的

List paramsList = new ArrayList();

/*

* 添加我们要的参数,这些可以通过查看浏览器中的网络看到,如下面我的截图中看到的一样

* 不论你用的是firebut,httpWatch或者是谷歌自带的查看器也好,都能查看到(后面会推荐辅助工具来查看)

* 要把表单需要的参数都填齐,顺序不影响

*/

paramsList.add(new BasicNameValuePair("Submit", ""));

paramsList.add(new BasicNameValuePair("fowardURL", "http://www.tianya.cn"));

paramsList.add(new BasicNameValuePair("from", ""));

paramsList.add(new BasicNameValuePair("method", "name"));

paramsList.add(new BasicNameValuePair("returnURL", ""));

paramsList.add(new BasicNameValuePair("rmflag", "1"));

paramsList.add(new BasicNameValuePair("__sid", "1#1#1.0#a6c606d9-1efa-4e12-8ad5-3eefd12b8254"));

// 你可以申请一个天涯的账号 并在下两行代码中替换为你的用户名和密码

paramsList.add(new BasicNameValuePair("vwriter", "ifugletest2014"));// 替换为你的用户名

paramsList.add(new BasicNameValuePair("vpassword", "test123456"));// 你的密码

// 将这个参数list设置到post中

post.setEntity(new UrlEncodedFormEntity(paramsList, Consts.UTF_8));

return post;

}

}

  执行上面的Main函数会得到如下结果:

  我们看到响应码确实是200,表示成功。其实这个响应相当于302,需要跳转,只不过它的跳转写在js的body部分。

  

  location.href=”http://passport.tianya.cn:80/online/loginSuccess.jsp?fowardurl=http%3A%2F%2Fwww.tianya.cn%2F94693372&userthird=&regOrlogin=%E7%99%BB%E5%BD%95%E4%B8%AD……&t=1410746182629&k=8cd4d967491c44c5eab1097e0f30c054&c=6fc7ebf8d782a07bb06624d9c6fbbf3f”;

  这是页面跳转

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线