赞
踩
爬虫不算特别陌生了,尤其是python崛起后,很多推广python的方式就是做爬虫的案例,例如可以爬取新闻网站等等,代码量不多,而且开发还有成就感。下面就说说对爬虫的一些思考。
网站的分类
网站我分为了两类
一种是表现结果是静态的,例如新闻网站,一个新闻一旦发布出来,url内容就不会改变了。并不会因为时间的变化,新闻内容而改变。还有公告网站,公告都贴出来了,如果更新也是弄一页新的,或者是更新内容,并不会有更多的交互部分。
一种是前后台分离的动态网站,例如获取新的数据来展示table,进行分页查询,还有例如erp系统,动态的增加数据,刷新数据,页面的东西可以说是时时刻刻在变动,格式都是固定的,只是数据每次都把新的填充进来。
很多教程都是第一种网站,爬取基本不动的内容。里面的数据,格式都是固定的,我们爬取获取到html。把前端的数据根据一定的规则获取出来。
第二种一般不会拿来做为入门手段。因为这种系统一般都包含校验,权限控制,例如我们可能必须登录才能做后面的操作,并不能直接那个url就是html。
浏览器
对于第二种情况,我们不妨思考一下,浏览器是什么。
浏览器是一个程序,帮助我们进行http请求,并且可以获取到返回的数据,而且本地可以存cookie,下次请求可以携带这些数据。
我们最开始做的登录系统,就是把用户的登录信息存到session里。由于session成功创建,请求返回时,头里带了jsessionid的信息,下次如果再次请求,都会携带这些信息。后台程序可以根据这个数据来进行校验,判断这个url是否能正常进行访问。
模拟浏览器
上面的例子大概说了我们编程的方式,还有浏览器的功能,是不是说我们可以通过模拟浏览器来达到这个效果呢。
如果是java的代码,我们去搜索,很大程度,搜到的结果就是以下两个关键字,webmagic,selenium。webmagic是爬虫框架。selenium是浏览器驱动,可以模拟浏览器获取到本地的cookies。然后用webmagic进行访问的时候可以增加对应的cookies。
但是我的思路不是这样的,因为前后台分离的情况下,后台返回的数据才是我们要获取的,我们爬取的不应该是页面了,而是通过模拟浏览器的功能直接获取到返回的数据。
我们都知道http协议是明文的。我们可以通过浏览器开启watch功能,看到请求发起以后传递的数据,请求头,请求体;以及请求返回后获取的响应头和响应体。
那我们自己就可以保存这些数据了,自己把cookies获取到,下次发起请求的时候就可以加入了。
httpclient
经过上面的分析,貌似情况简单了,我们只用httpclient就可以做到了。首先第一步是获取请求,这里我们推荐使用抓包工具,而不是浏览器自带的。在一些重定向的操作中,自带的工具很可能抓不到。
下面是模拟浏览器的代码,就是在协议里告诉后台程序,我们是什么
private static void setPostHeader(HttpPost httpPost) {
httpPost.setHeader("X-Requested-With", "XMLHttpRequest");
httpPost.setHeader("Accept", "application/json, text/javascript, */*; q=0.01");
httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36");
}
请求的代码直接发出来
//创建httpclient对象
CloseableHttpClient client = HttpClients.createDefault();
//创建post方式请求对象
HttpPost httpPost = new HttpPost(URL);
//装填参数
List nvps = new ArrayList();
nvps.add(new BasicNameValuePair("password", "xxxxx"));
//设置参数到请求对象中
httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));
setPostHeader(httpPost);
//执行请求操作,并拿到结果(同步阻塞)
CloseableHttpResponse response = client.execute(httpPost);
//获取结果实体
HttpEntity entity = response.getEntity();
if (entity != null) {
//按指定编码转换结果实体为String类型
body = EntityUtils.toString(entity, "UTF-8");
}
Header[] allHeaders = response.getAllHeaders();
if (body.contains("success")) {
List cookiesTmp = new ArrayList<>();
for (Header allHeader : allHeaders) {
if ("Set-Cookie".equals(allHeader.getName())) {
String[] split = allHeader.getValue().split(";");
if (split.length > 0) {
cookiesTmp.add(split[0] + ";");
}
}
}
cookies = cookiesTmp;
}
EntityUtils.consume(entity);
//释放链接
response.close();
代码逻辑很简单,创建连接,设置头,和参数。在成功后把cookies 获取出来,再下次请求的时候再带上。
private String setCookies() {
StringBuilder sb = new StringBuilder();
final List cookiesTmp = cookies;
for (String cookie : cookiesTmp) {
sb.append(cookie);
}
return sb.toString();
}
设置的方式就是明文,这里需要参考具体的http请求来做。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。