欢迎访问我的个人网站,要是能在GitHub上对网站源码给个star就更好了。

搭建自己的网站的时候,想把自己读过借过的书都想记录一下,大学也做过自己学校的借书记录的爬取,但是数据库删掉了==,只保留一张截图。所以还是要好好珍惜自己阅读的日子吧,记录自己的借书记录——广州图书馆,现在代码已经放在服务器上定时运行,结果查看我的网站(关于我)页面。整个代码采用HttpClient,存储放在MySql,定时使用Spring自带的Schedule,下面是抓取的过程。

1.页面跳转过程

一般都是进入首页http://www.gzlib.gov.cn/,点击进登陆页面,然后输入账号密码。表面上看起来没什么特别之处,实际上模拟登陆的时候不仅仅是向链接post一个请求那么简单,得到的response要么跳回登陆页面,要么无限制重定向。

事实上,它做了单点登录,如下图,广州图书馆的网址为:www.gzlib.gov.cn,而登陆的网址为:login.gzlib.gov.cn。原理网上很多人都讲的很好了,可以看看这篇文章SSO单点登录。

2.处理方法

解决办法不难,只要先模拟访问一下首页即可获取图书馆的session,python的获取代码如:session.get("http://www.gzlib.gov.cn/"),打印cookie之后如下:

[<Cookie JSESSIONID=19E2DDED4FE7756AA9161A52737D6B8E for .gzlib.gov.cn/>, <Cookie JSESSIONID=19E2DDED4FE7756AA9161A52737D6B8E for www.gzlib.gov.cn/>, <Cookie clientlanguage=zh_CN for www.gzlib.gov.cn/>]

整个登陆抓取的流程如下:

即:
(1)用户先点击广州图书馆的首页,以获取改网址的session,然后点击登录界面,解析html,获取lt(自定义的参数,类似于验证码),以及单点登录服务器的session。
(2)向目标服务器(单点登录服务器)提交post请求,请求参数中包含username(用户名),password(密码),event(时间,默认为submit),lt(自定义请求参数),同时服务端还要验证的参数:refer(来源页面),host(主机信息),Content-Type(类型)。
(3)打印response,搜索你自己的名字,如果有则表示成功了,否则会跳转回登陆页面。
(4)利用cookie去访问其他页面,此处实现的是对借阅历史的抓取,所以访问的页面是:http://www.gzlib.gov.cn/member/historyLoanList.jspx。

基本的模拟登陆和获取就是这些,之后还有对面html的解析,获取书名、书的索引等,然后封装成JavaBean,再之后便是保存入数据库。(去重没有做,不知道用什么方式比较好)

3.代码

3.1 Java中,一般用来提交http请求的大部分用的都是httpclient,首先,需要导入的httpclient相关的包:

<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpclient</artifactId><version>4.5.3</version>
</dependency>
<dependency><groupId>org.apache.httpcomponents</groupId><artifactId>httpcore</artifactId><version>4.4.7</version>
</dependency>

3.2 构建声明全局变量——上下文管理器,其中context为上下文管理器

public class LibraryUtil {private static CloseableHttpClient httpClient = null;private static HttpClientContext context = null;private static CookieStore cookieStore = null;static {init();}private static void init() {context = HttpClientContext.create();cookieStore = new BasicCookieStore();// 配置超时时间RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(12000).setSocketTimeout(6000).setConnectionRequestTimeout(6000).build();// 设置默认跳转以及存储cookiehttpClient = HttpClientBuilder.create().setKeepAliveStrategy(new DefaultConnectionKeepAliveStrategy()).setRedirectStrategy(new DefaultRedirectStrategy()).setDefaultRequestConfig(requestConfig).setDefaultCookieStore(cookieStore).build();}...

3.3 声明一个get函数,其中header可自定义,此处不需要,但是保留着,做成一个通用的吧。

    public static CloseableHttpResponse get(String url, Header[] header) throws IOException {HttpGet httpget = new HttpGet(url);if (header != null && header.length > 0) {httpget.setHeaders(header);}CloseableHttpResponse response = httpClient.execute(httpget, context);//context用于存储上下文return response;}

3.4 访问首页以获得session,服务器上会话是使用session存储的,本地浏览器使用的是cookie,只要本地不退出,那么使用本地的cookie来访问也是可以的,但是为了达到模拟登陆的效果,这里就不再阐述这种方式。

CloseableHttpResponse homeResponse = get("http://www.gzlib.gov.cn/", null);
homeResponse.close();

此时,如果打印cookie,可以看到目前的cookie如下:

<RequestsCookieJar[
<Cookie JSESSIONID=54702A995ECFC684B192A86467066F20 for .gzlib.gov.cn/>,
<Cookie JSESSIONID=54702A995ECFC684B192A86467066F20 for www.gzlib.gov.cn/>,
<Cookie clientlanguage=zh_CN for www.gzlib.gov.cn/>]>

3.5 访问登陆页面,获取单点登录服务器之后的cookie,解析网页,获取自定义参数lt。这里的解析网页使用了Jsoup,语法和python中的BeautifulSoup中类似。

String loginURL = "http://login.gzlib.gov.cn/sso-server/login?service=http%3A%2F%2Fwww.gzlib.gov.cn%2Flogin.jspx%3FreturnUrl%3Dhttp%253A%252F%252Fwww.gzlib.gov.cn%252F%26locale%3Dzh_CN&appId=www.gzlib.gov.cn&locale=zh_CN";
CloseableHttpResponse loginGetResponse = get(loginURL, null);
String content = toString(loginGetResponse);
String lt = Jsoup.parse(content).select("form").select("input[name=lt]").attr("value");
loginGetResponse.close();

此时,再次查看cookie,多了一个(www.gzlib.gov.cn/sso-server):

<RequestsCookieJar[
<Cookie JSESSIONID=54702A995ECFC684B192A86467066F20 for .gzlib.gov.cn/>,
<Cookie JSESSIONID=54702A995ECFC684B192A86467066F20 for www.gzlib.gov.cn/>,
<Cookie clientlanguage=zh_CN for www.gzlib.gov.cn/>,
<Cookie JSESSIONID=9918DDF929757B244456D4ECD2DAB2CB for www.gzlib.gov.cn/sso-server/>]>

3.6 声明一个post函数,用来提交post请求,其中提交的参数默认为

    public static CloseableHttpResponse postParam(String url, String parameters, Header[] headers)throws IOException {System.out.println(parameters);HttpPost httpPost = new HttpPost(url);if (headers != null && headers.length > 0) {for (Header header : headers) {httpPost.addHeader(header);}}List<NameValuePair> nvps = toNameValuePairList(parameters);httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));CloseableHttpResponse response = httpClient.execute(httpPost, context);return response;}

3.7 登陆成功后,如果没有声明returnurl,即登录链接为(http://login.gzlib.gov.cn/sso-server/login),那么只是会显示成功登录的页面:

后台应该是定义了一个service用来进行链接跳转的,想要获取登录成功之后的跳转页面可修改service之后的链接,这里将保持原始状态。此时,查看cookie结果如下:

<RequestsCookieJar[
<Cookie JSESSIONID=54702A995ECFC684B192A86467066F20 for .gzlib.gov.cn/>,
<Cookie JSESSIONID=54702A995ECFC684B192A86467066F20 for www.gzlib.gov.cn/>,
<Cookie clientlanguage=zh_CN for www.gzlib.gov.cn/>,
<Cookie CASTGC=TGT-198235-zkocmYyBP6c9G7EXjKyzgKR7I40QI4JBalTkrnr9U6ZkxuP6Tn for www.gzlib.gov.cn/sso-server>,
<Cookie JSESSIONID=9918DDF929757B244456D4ECD2DAB2CB for www.gzlib.gov.cn/sso-server/>]>

其中,出现CASTGC表明登陆成功了,可以使用该cookie来访问广州图书馆的其他页面,在python中是直接跳转到其他页面,而在java使用httpclient过程中,看到的并不是直接的跳转,而是一个302重定向,打印Header之后结果如下图:

认真研究一下链接,就会发现服务器相当于给了一张通用票ticket,即:可以使用该ticket访问任何页面,而returnUrl则是返回的页面。这里我们直接访问该重定向的url。

Header header = response.getHeaders("Location")[0];
CloseableHttpResponse home = get(header.getValue(), null);

然后打印页面,即可获取登陆之后跳回的首页。

3.8 解析html
获取session并跳回首页之后,再访问借阅历史页面,然后对结果进行html解析,python中使用了BeautifulSoup,简单而又实用,java中的jsoup也是一个不错的选择。

        String html = getHTML();Element element = Jsoup.parse(html).select("table.jieyue-table").get(0).select("tbody").get(0);Elements trs = element.select("tr");for (int i = 0; i < trs.size(); i++) {Elements tds = trs.get(i).select("td");System.out.println(tds.get(1).text());}

输出结果:

企业IT架构转型之道
大话Java性能优化
深入理解Hadoop
大话Java性能优化
Java EE开发的颠覆者:Spring Boot实战
大型网站技术架构:核心原理与案例分析
Java性能权威指南
Akka入门与实践
高性能网站建设进阶指南:Web开发者性能优化最佳实践:Performance best practices for Web developers
Java EE开发的颠覆者:Spring Boot实战
深入理解Hadoop
大话Java性能优化

点击查看源码

总结

目前,改代码已经整合进个人网站之中,每天定时抓取一次,但是仍有很多东西没有做(如分页、去重等),有兴趣的可以研究一下源码,要是能帮忙完善就更好了。感谢Thanks♪(・ω・)ノ。整个代码接近250行,当然...包括了注释,但是使用python之后,也不过25行=w=,这里贴一下python的源码吧。同时,欢迎大家访问我的个人网站,也欢迎大家能给个star。

import urllib.parse
import requests
from bs4 import BeautifulSoupsession = requests.session()
session.get("http://www.gzlib.gov.cn/")
session.headers.update({"Referer": "http://www.gzlib.gov.cn/member/historyLoanList.jspx","origin": "http://login.gzlib.gov.cn",'Content-Type': 'application/x-www-form-urlencoded','host': 'www.gzlib.gov.cn','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36'}
)
baseURL = "http://login.gzlib.gov.cn/sso-server/login"
soup = BeautifulSoup(session.get(baseURL).text, "html.parser")
lt = soup.select("form")[0].find(attrs={'name': 'lt'})['value']
postdict = {"username": "你的身份证","password": "密码(默认为身份证后6位)","_eventId": "submit","lt": lt}
postdata = urllib.parse.urlencode(postdict)
session.post(baseURL, postdata)
print(session.get("http://www.gzlib.gov.cn/member/historyLoanList.jspx").text)

转载于:https://www.cnblogs.com/w1570631036/p/7666241.html

广州图书馆借阅抓取——httpClient的使用相关推荐

  1. java爬取验证码图片_JAVA HttpClient实现页面信息抓取(获取图片验证码并传入cookie实现信息获取)...

    JAVA HttpClient实现页面信息抓取(获取图片验证码并传入cookie实现信息获取) 发布时间:2018-05-18 16:41, 浏览次数:632 , 标签: JAVA HttpClien ...

  2. HttpClient+Jericho HTML Parser 实现网页的抓取

    //转自:chenqi19831112/archive/2008/11/07/3248863.aspx Jericho HTML Parser是一个简单而功能强大的Java HTML解析器库,可以分析 ...

  3. apache httpclient 工具类_Java教程分享使用HttpClient抓取页面内容

    Java教程分享使用HttpClient抓取页面内容,使用HttpClient工具来发送Http请求 1.简介 HttpClient 是 Apache Jakarta Common 下的子项目,用来提 ...

  4. 使用HttpClient实现一个简单爬虫,抓取煎蛋妹子图

    第一篇文章,就从一个简单爬虫开始吧. 这只虫子的功能很简单,抓取到"煎蛋网xxoo"网页(http://jandan.net/ooxx/page-1537),解析出其中的妹子图,保 ...

  5. java response 获得code_Java教程分享使用HttpClient抓取页面内容

    Java教程分享使用HttpClient抓取页面内容,使用HttpClient工具来发送Http请求 1.简介 HttpClient 是 Apache Jakarta Common 下的子项目,用来提 ...

  6. Java爬虫系列二:使用HttpClient抓取页面HTML

    爬虫要想爬取需要的信息,首先第一步就要抓取到页面html内容,然后对html进行分析,获取想要的内容.上一篇随笔<Java爬虫系列一:写在开始前>中提到了HttpClient可以抓取页面内 ...

  7. 网页爬虫,HttpClient+Jericho HTML Parser 实现网页的抓取

    Jericho HTML Parser是一个简单而功能强大的Java HTML解析器库,可以分析和处理HTML文档的一部分,包括一些通用的服务器端标签,同时也可以重新生成无法识别的或无效的HTML.它 ...

  8. Python爬虫实战---抓取图书馆借阅信息

    Python爬虫实战---抓取图书馆借阅信息 原创作品,引用请表明出处:Python爬虫实战---抓取图书馆借阅信息 前段时间在图书馆借了很多书,借得多了就容易忘记每本书的应还日期,老是担心自己会违约 ...

  9. 用httpclient抓取全国火车票信息

    一个通过httpclient抓取火车票信息的程序,需要修改下才能跑通,需要自己封装下httpclient,然后用get方式调用,还有fastJson,需要自己去解析下获得的数据,catchTrainI ...

最新文章

  1. asp实现UNIX时间戳功能
  2. python单链表实现荷兰国旗问题_这道荷兰旗问题,我面试时遇到三次!
  3. python官网怎么下载安装-Python怎么下载安装
  4. 破解入门(六)-----实战“内存镜像法”脱壳
  5. Spring中Bean的配置方式之通过全类名(反射)
  6. 抖音怎么设置保存路径_抖音限时可见视频怎么弄 设置限时可见作品方法
  7. 进击的新势力·95后短视频冲浪与消费图鉴2021
  8. java url 传值乱码问题_java页面url传值中文乱码怎么办
  9. hidefocus小技巧
  10. Python 代码覆盖率统计工具 coverage.py
  11. 碰到一个非常郁闷的事
  12. 威纶触摸屏485轮询通讯_威纶触摸屏Modbus TCP\RTU\ASCII通信视频教程
  13. 2019开放大学计算机应用基础,国家开放大学2019年电大计算机应用基础考试试题一试卷(国家开放大学).doc...
  14. html制作论坛页面模板,Discuz3.3仿小米论坛风格整站模板制作教程——1、新建模板方案...
  15. 深度学习调参经验分享(遥感建筑提取)
  16. 特斯拉将粉丝创意注册为商标 包括电动皮卡版书包
  17. 三个步骤教你如何做好后台产品设计
  18. Google工作10年的职场感悟
  19. 2021牛客多校#4 E-Tree Xor
  20. python 例子 银行_Python3实现简单的银行账户登录系统实例

热门文章

  1. JavaScript常用函数
  2. R语言:使用REmap绘制超炫酷的地图
  3. python搭建环境是什么_python虚拟环境是什么?python虚拟环境的介绍
  4. python笔试题110题_《Python程序设计》试题库
  5. matlab将图片转换为灰度图_视频处理之灰度图
  6. 改变路径但是不让它跳转_Vue实战047:Breadcrumb面包屑实现导航路径
  7. java飞行器服务端_使用jvisualvm和飞行记录器分析Java程序cpu占用率过高
  8. oracle 关联出现重复数据,ORACLE 分页查询出现重复记录的解决办法
  9. ViSP中识别AprilTag的C++实例代码解释
  10. 列标题 如何删除gridcontrol_DEV控件GridControl常用属性设置(转)