Apache HttpComponents中的cookie匹配策略

*/-->

pre.src {background-color: #292b2e; color: #b2b2b2;}

pre.src {background-color: #292b2e; color: #b2b2b2;}

pre.src {background-color: #292b2e; color: #b2b2b2;}

pre.src {background-color: #292b2e; color: #b2b2b2;}

pre.src {background-color: #292b2e; color: #b2b2b2;}

pre.src {background-color: #292b2e; color: #b2b2b2;}

Apache HttpComponents中的cookie匹配策略

目录

  • 1. 简介
  • 2. 示例

1 简介

在clojure中使用clj-http抓取网页时,需要提交自定义cookie,总是不能成功发送,研究一下HttpClient中Cookie的工作方式。

clj-http包装了HttpClient库,对于请求页面时发回的状态可以自动处理,但是需要自己往请求中添加cookie时总是失败,折腾了很久,了解了HttpClient处理Cookie的细节,关于HttpClient中HTTP的状态管理,可以参考HttpClient的官方指南

2 示例

从bing获取搜索结果,代码如下:

deps.edn文件如下:

{
 :deps {
        org.clojure/clojure {:mvn/version "1.10.0"},
        clj-http {:mvn/version "3.9.1"}, ; http
        reaver {:mvn/version "0.1.2"}  ; jsoup, html parser
        }
}

实际代码:

(require ‘[clj-http.client :as client])
(require ‘[clj-http.cookies :as cookies])
(require ‘[reaver :as html])

(def ua "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20120101 Firefox/33.0")
(def cs (cookies/cookie-store))

(def http-header {:headers {"user-agent" ua
                            "accept-charset" "utf-8"}
                  :proxy-host "localhost" ;本地代理,用于测试
                  :proxy-port 8080
                  :cookie-store cs
                  :insecure? true})

(defn search
  "搜索关键字kw,返回[{:url :title :desc} ...]
  kw 为搜索关键字
  opt为附加选项:
  :option http请求额外参数
  :max-page 查询的最大页数,默认为3"
  [kw & [opt]]
  (let [base-url "https://www.bing.com"
        option (get opt :option {})
        max-page (get opt :max-page 3)]
    (loop [page 1
           url (str base-url "/search?q=" kw) ;这里没有用url编码,仅为演示用
           result []]
      (if (> page max-page)
        result
        (let [doc (-> (client/get url
                                  (merge http-header option))
                      :body
                      html/parse)
              entrys (html/extract-from doc "li.b_algo"
                                        [:url :title :desc]
                                        "h2 > a" (html/attr "href")
                                        "h2 > a" html/text
                                        "div > p" html/text)
              r (apply conj result entrys)]
          (if-let [next-path (-> (html/select doc "a.sb_pagn" )
                                 (html/attr "href"))]
            (recur (inc page)
                   (str base-url next-path)
                   r)
            r))))))

(def googles (search "google" {:max-page 3}))
(count googles)
;; => 30
(first googles)
;; => {:url "http://www.google.cn/", :title "Google", :desc "2016-12-8 · google.com.hk 请收藏我们的网址"}

可以看到一页返回10个结果,如果要返回50(bing设置里最大结果数量),则要设置cookie项:
"SRCHHPGUSR" 的值为: "NRSLT=50"

下面添加cookie:

(cookies/clear-cookies cs) ;清除之前请求产生的cookies

(def usr-cookie (cookies/to-basic-client-cookie
                 ["SRCHHPGUSR" {
                                :discard false
                                :domain ".bing.com",
                                :path "/",
                                :value "NRSLT=50"
                                :expires (java.util.Date. 9000 1 1)
                                }]))
(cookies/add-cookie cs usr-cookie)

(cookies/get-cookies cs)
;; => {"SRCHHPGUSR" {:discard false, :domain ".bing.com", :expires #inst "10900-01-31T16:00:00.000-00:00", :path "/", :secure false, :value "NRSLT=50", :version 0}}

(def googles (search "google" {:max-page 3}))
(count googles)
;; => 30

可以看到cookie并没有生效,在代理中也可以看到第一次请求时并没有带上添加的cookie。原因是HttpClient默认的Cookie specifications不会把.bing.com匹配到www.bing.com。

下面Api用法可以参考CookieOrigin API文档cookie package文档:

(import org.apache.http.cookie.CookieOrigin)
(import (org.apache.http.impl.cookie DefaultCookieSpec
                                     RFC6265LaxSpec
                                     RFC6265StrictSpec
                                     RFC2965Spec
                                     RFC2109Spec
                                     NetscapeDraftSpec
                                     IgnoreSpec
                                     BasicClientCookie2))

(def bing-co (CookieOrigin. "www.bing.com" 80 "/" false))

(def match-spec #(.match %1 usr-cookie bing-co))
(def default-spec (DefaultCookieSpec.))
(match-spec default-spec)
;; => false
(def rfc6265-lax-spec (RFC6265LaxSpec.))
(match-spec rfc6265-lax-spec)
;; => false
(def rfc6265-strict-spec (RFC6265StrictSpec.))
(match-spec rfc6265-strict-spec)
;; => false
(def rfc2965-spec (RFC2965Spec.))
(match-spec rfc2965-spec)
;; => true
(def rfc2109-spec (RFC2109Spec.))
(match-spec rfc2109-spec)
;; => true
(def netscape-spec (NetscapeDraftSpec.))
(match-spec netscape-spec)
;; => true

;; 通过测试的几个spec,可以看到,默认只有rfc2*和netscape可以匹配.bing.com
;; 下面设置cookie的attr
(str usr-cookie)
;; => "[version: 0][name: SRCHHPGUSR][value: NRSLT=50][domain: .bing.com][path: /][expiry: Mon Feb 01 00:00:00 CST 10900]"
(.setAttribute usr-cookie BasicClientCookie2/DOMAIN_ATTR "true")
(str usr-cookie)
;; => "[version: 0][name: SRCHHPGUSR][value: NRSLT=50][domain: .bing.com][path: /][expiry: Mon Feb 01 00:00:00 CST 10900]"
;; 从表面上看不出设置了attr的区别,只有匹配时不同:
(.getAttribute usr-cookie "domain") ; DOMAIN_ATTR的值是"domain"
;; => "true"

(def match-spec #(.match %1 usr-cookie bing-co))
(match-spec default-spec)
;; => true
(match-spec rfc6265-lax-spec)
;; => true
(match-spec rfc6265-strict-spec)
;; => true
(match-spec rfc2965-spec)
;; => true
(match-spec rfc2109-spec)
;; => true
(match-spec netscape-spec)
;; => true

;;再看搜索结果
(cookies/clear-cookies cs)
(cookies/add-cookie cs usr-cookie)
(def googles (search "google" {:max-page 3}))
(count googles)
;; => 78
;; 不是每页都有50条,不过重要的是通过.setAttribute,cookie起作用了

具体原因是rfc6265的规定,参考overflow的回答

经过上面的测试,也可以在clj-http中使用netscape的cookie-policy来达到目的,因为standard属于rfc6265-lax,默认也不会匹配:

(def usr-cookie (cookies/to-basic-client-cookie
                 ["SRCHHPGUSR" {
                                :discard false
                                :domain ".bing.com",
                                :path "/",
                                :value "NRSLT=50"
                                :expires (java.util.Date. 9000 1 1)
                                }]))

(cookies/clear-cookies cs)
(cookies/add-cookie cs usr-cookie)
(def googles (search "google" {:max-page 3
                               :option {:cookie-policy :netscape}}))
(count googles)
;; => 78

但是这种方法是不推荐的,还是用.setAttribute比较好。

作者: ntestoc

Created: 2019-01-25 五 20:18

原文地址:https://www.cnblogs.com/ntestoc/p/10321423.html

时间: 2024-10-11 21:10:38

Apache HttpComponents中的cookie匹配策略的相关文章

在 Apache error_log 中看到多个信息,提示 RSA server certificate CommonName (CN) 与服务器名不匹配(转)

在 Apache error_log 中看到多个信息,提示 RSA server certificate CommonName (CN) 与服务器名不匹配. Article ID: 1500, created on 五月 28, 2012, last review on 五月 11, 2014 适用于: Web Presence Builder Plesk for Linux/Unix Plesk Automation 11.5 问题 Apache error_log 含有警告: [Mon Se

RTB竞价中的cookie mapping技术

首先通过一些关键词解释普及或者回顾一下背景, ADX: Ad exchange的简称.一般特指Ad exchange平台模块 DMP: Data Management Platform的简称.DMP存储了流量.受众的各种特征信息. DSP: Demand Side Platform的简称.可以看做流量的购买方,为广告主服务.广告主可以通过DSP购买流量,达到营销的目的.DSP可以接入ad exchange中,参与cpm竞价,购买所需要的受众流量. SSP: Supply Side Platfor

JavaScript中设置cookie的值

cookie 与 session 是网页开发中常用的信息存储方式.Cookie是在客户端开辟的一块可存储用户信息的地方:Session是在服务器内存中开辟的一块存储用户信息的地方.JavaScript是运行在客户端的脚本,因此一般是不能够设置Session的,因为Session是运行在服务器端的,而cookie是运行在客户端的,所以可以用JS来设置cookie. 在ITOO项目中,系统需要页面之间的传值,现在假设页面A,和页面B,页面B需要页面A的一个参数,才可以进行后面的操作,那么我们就需要将

android中如何处理cookie

Managing Cookies HttpClient provides cookie management features that can be particularly useful to test the way an application handles cookies. Listing 9-3 shows an example where you use HttpClient to add a cookie to a request and also to list detail

关于安卓中的cookie管理

Cookie管理是大家在做安卓app中难以避免的问题.我在此发表一些拙见. 先先看看cookie可能存放的位置 1.Httpclient会存储当次请求的cookie内容,存储位置在 httpClient.getCookieStore 但是apache建议自定义cookie存储方式,因为cookiestore把cookie放在arraylist里很容易被系统回收[1]. 2.WebView会存储cookie在CookieManager,具体使用方式,后续的文章会讲这里不是重点. 正常HttpCli

Apache配置文件中的deny和allow的使用

Apache配置文件中的deny和allow的使用 由于产品的需要,最近在配置apache的负载均衡功能,但是在配置虚拟主机的访问权限的时候我们遇到了一些问题.主要问题是deny和allow的执行顺序,抽时间研究了下这两个参数的使用,现把deny和allow的使用情况总结如下. 一.   使用情况总结 我们来看下下面的apache的一个配置,具体代码如下: <Directory /> Order allow,deny  #1 Allow from all #2 deny from 192.9.

WEB中的cookie

首先来一篇好文章,刚好看到的: 沉默中的狂怒 —— Cookie 大喷发---------------- http://www.cnblogs.com/index-html/p/mitm-cookie-sniffer.html#3050493 我就重复一遍啦: 在chrome或者firefox下登陆下163的邮箱: 在控制台执行js: new Image().src = "http://push.webmail.mail.163.com"; 在控制台可以看到发送的的请求的Request

IM开发基础知识补课(四):正确理解HTTP短连接中的Cookie、Session和Token

本文引用了简书作者“骑小猪看流星”技术文章“Cookie.Session.Token那点事儿”的部分内容,感谢原作者. 1.前言 众所周之,IM是个典型的快速数据流交换系统,当今主流IM系统(尤其移动端IM)的数据流交换方式都是Http短连接+TCP或UDP长连接来实现.Http短连接主要用于从服务器读取各种持久化信息:比如用户信息.聊天历史记录.好友列表等等,长连接则是用于实时的聊天消息或指令的接收和发送. 作为IM系统中不可或缺的技术,Http短连的重要性无可替代,但Http作为传统互联网信

Apache HttpComponents 工具类 [ HttpUtil ]

pom.xml <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5.5</version> </dependency> <dependency> <groupId>org.apache.httpcomponents</gr