httpclient 抓取网页(2021-05-24欢迎访问我的个人网站-广州图书馆)

优采云 发布时间: 2022-04-19 19:18

  httpclient 抓取网页(2021-05-24欢迎访问我的个人网站-广州图书馆)

  2021-05-24

  欢迎来到我的个人网站,如果能在GitHub上给网站的源码打个star就更好了。

  在构建自己的网站时,我想记录我读过和借过的所有书。大学也爬过自己学校的借阅记录,但是数据库已经被删除了==,只有一张截图。所以你要珍惜你阅读的日子,记录你的借阅记录——广州图书馆,现在代码已经放到服务器上定期运行,结果查看我的网站(关于我)页面。整个代码使用HttpClient,存储在MySql中,定期使用Spring自带的Schedule。下面是爬取的过程。

  1.页面跳转过程

  一般是进入首页,点击进入登录页面,然后输入账号密码。从表面上看,它似乎并没有什么特别之处。事实上,在模拟登录的时候,并不仅仅是向链接发布请求那么简单。生成的响应将跳转回登录页面或无限制地重定向。

  

  其实就是做单点登录的,如下图,广州图书馆的网址是:,登录的网址是:。网上很多人都很好的解释了原理。您可以阅读此 文章SSO 单点登录。

  

  2.处理方式

  解决方法不难,只要先模拟访问首页获取库的session,python获取代码如:session.get(""),打印cookie后如下:

  [, , ]

  整个登录和抓取过程如下:

  

  这是:

  (1)用户先点击广州图书馆首页,获取换站session,然后点击登录界面,解析html,获取lt(自定义参数,类似验证码),单点登录服务器会话。

  (2)向目标服务器(单点登录服务器)提交post请求,请求参数包括username(用户名)、password(密码)、event(时间,默认为submit)、lt(自定义request parameters) ,服务器还需要对参数进行校验:refer(源页面)、host(主机信息)、Content-Type(类型)。

  (3)打印响应,搜索自己的名字,如果有则表示成功,否则会跳转回登录页面。

  (4)使用cookies访问其他页面,这里是借阅历史的爬取,所以访问的页面是:.

  这是基本的模拟登录和获取,然后是对面的html的解析,得到书名、书索引等,然后封装成JavaBean,然后存入数据库。(没做过,不知道用什么方法比较好)

  3.代码

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

  

org.apache.httpcomponents

httpclient

4.5.3

org.apache.httpcomponents

httpcore

4.4.7

  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();

// 设置默认跳转以及存储cookie

httpClient = 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存储的,本地浏览器使用cookies。只要本地不注销,也可以使用本地cookie访问,但是为了达到模拟登录的效果,这里不再赘述。

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

homeResponse.close();

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

  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,又多了一个():

  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 nvps = toNameValuePairList(parameters);

httpPost.setEntity(new UrlEncodedFormEntity(nvps, "UTF-8"));

CloseableHttpResponse response = httpClient.execute(httpPost, context);

return response;

}

  3.7 登录成功后,如果没有声明returnurl,即登录链接为(),那么只会显示登录成功页面:

  

  后台应该定义一个链接跳转的服务。如果想在登录成功后得到跳转页面,可以在服务后修改链接,这里会保持原来的状态。此时查看cookie的结果如下:

  其中,CASTGC的出现说明登录成功,该cookie可用于访问广州图书馆的其他页面。在python中是直接跳转到其他页面,但是在java中使用httpclient的过程中,看到的并不是直接跳转。,但 302 重定向。打印Header后,结果如下:

  

  如果你仔细研究一下链接,你会发现服务器相当于给了一张通用票,即:你可以用这张票访问任何页面,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性能优化

  点击查看源代码

  总结

  目前修改后的代码已经集成到个人网站中,每天定时抓取,但是还有很多事情没有做(比如分页、去重等),如果你有兴趣的可以研究下源码,如果能帮助改进就更好了。谢谢♪(・ω・)ノ。整个代码接近250行,当然……包括注释,但是使用python后,只有25行=w=,这里是python的源代码。同时也欢迎大家访问我的个人网站,也欢迎大家给个star。

  import urllib.parse

import requests

from bs4 import BeautifulSoup

session = 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)

  分类:

  技术要点:

  相关文章:

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线