首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有cookies的HTTPoison

带有cookies的HTTPoison
EN

Stack Overflow用户
提问于 2016-01-19 01:20:09
回答 1查看 1.6K关注 0票数 1

我想刮掉一个网站。我想要抓取的网站没有API。

我想要做的是(在Python中):

代码语言:javascript
复制
import requests

with requests.Session() as conn:
    url = "http://demo.ilias.de/login.php"
    auth = {
        "username": "benjamin",
        "password": "iliasdemo"
    }
    conn.post(url, data=auth)
    response = conn.get(url)
    do_work(response)

当尝试使用HTTPoison做同样的事情时,网站会响应“请在浏览器中启用会话cookie!”。灵丹妙药代码:

代码语言:javascript
复制
HTTPoison.post "http://demo.ilias.de/login.php", 
  "{\"username\":\"benjamin\", \"password\":\"iliasdemo\"}"

我猜问题出在饼干上。

UPD#1。似乎并不是所有的cookies都会被保存,因为:hackney.cookies(headers) (来自%HTTPoison.Response{headers: headers}headers)不会输出一些我在浏览器和上面的Python代码响应中看到的cookies (例如authchallenge)。有没有可能hackney实际上并没有张贴任何东西?

EN

回答 1

Stack Overflow用户

发布于 2017-11-19 23:37:41

我也遇到过类似的问题:

我向服务器api发出了一个GET请求,它在相同的位置以301重定向和一个带有sessionId的"Set-Cookie“头作为响应。如果您遵循重定向而不发回其cookie,则它们将以相同的重定向和一个新的SessionId cookie进行响应。如果你不把饼干寄回给他们,这种动机就会继续下去。另一方面,如果您将cookie发送给他们,他们会返回200状态代码和您要求的数据。

问题出在哈克尼,因此HTTPoison不能遵循这个场景。它实际上有一个:follow_redirect选项,当设置时,它跟随重定向,但在捕获cookie并在重定向之间发送它们方面做得不够。

我尝试过的所有浏览器(firefox、chrome、IE)都能通过这个场景。Python和wget也完成了这项工作。

总之,为了简短起见,我为我的案例写了一个变通方法,可能会给其他有类似问题的人提供一些想法:

代码语言:javascript
复制
defmodule GVHTTP do
  defmacro __using__(_) do
    quote do
      use HTTPoison.Base

      def cookies_from_resp_headers(recv_headers) when is_list(recv_headers) do
        List.foldl(recv_headers, [], fn
          {"Set-Cookie", c}, acc -> [c|acc]
          _, acc -> acc
        end)
        |> Enum.map(fn(raw_cookie) ->
            :hackney_cookie.parse_cookie(raw_cookie)
            |> (fn
                  [{cookie_name, cookie_value} | cookie_opts] ->
                    { cookie_name, cookie_value,
                      cookie_opts
                    }
                  _error ->
                    nil
                end).()
        end)
        |> Enum.filter(fn
          nil -> false
          _ -> true
        end)
      end

      def to_request_cookie(cookies) do
        cookies
        |> Enum.map(fn({ cookie_name, cookie_value, _cookie_opts}) ->
            cookie_name <> "=" <> cookie_value
          end)
        |> Enum.join("; ")
        |> (&("" == &1 && [] || [&1])).() # "" => [], "foo1=abc" => ["foo1=abc"]
      end

      def get(url, headers \\ [], options \\ []) do
        case options[:follow_redirect] do
          true ->
            hackney_options = case options[:max_redirect] do
              0 -> options # allow HTTPoison to handle the case of max_redirect overflow error
              _ -> Keyword.drop(options, [:follow_redirect, :max_redirect])
            end
            case request(:get, url, "", headers, hackney_options) do
              {:ok, %HTTPoison.Response{status_code: code, headers: recv_headers}} when code in [301, 302, 307] ->
                {_, location} = List.keyfind(recv_headers, "Location", 0)
                req_cookie =
                  cookies_from_resp_headers(recv_headers)
                  |> to_request_cookie()

                new_options =
                  options
                    |> Keyword.put(:max_redirect, (options[:max_redirect] || 5) - 1)
                    |> Keyword.put(:hackney, [cookie:
                        [options[:hackney][:cookie]|req_cookie]
                        |> List.delete(nil)
                        |> Enum.join("; ")
                      ]) # add any new cookies along with the previous ones to the request
                get(location, headers, new_options)
              resp ->
                resp
            end
          _ ->
            request(:get, url, "", headers, options)
        end
      end

    end # quote end
  end  # __using__ end
end
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34860496

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档