我想刮掉一个网站。我想要抓取的网站没有API。
我想要做的是(在Python中):
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!”。灵丹妙药代码:
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实际上并没有张贴任何东西?
发布于 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也完成了这项工作。
总之,为了简短起见,我为我的案例写了一个变通方法,可能会给其他有类似问题的人提供一些想法:
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
endhttps://stackoverflow.com/questions/34860496
复制相似问题