如何使用Jsoup维护变量cookie和session?

5
public boolean isGood(String path)
{
    if (p != path)
    {
        good = false;
    }

    if (good)
    {
        try 
        {
            Connection connection = Jsoup.connect(path);
            Map<String, String> cookys = Jsoup.connect(path).response().cookies();

            if (cookys != cookies)
                cookies = cookys;

            for (Entry<String, String> cookie : cookies.entrySet()) 
            {
                connection.cookie(cookie.getKey(), cookie.getValue());
            }

            Doc = connection.get();
            good = true;
        }
        catch (Exception e) 
        {
            rstring = e.getMessage().toString();
            good = false;
        }
    }
    else
    {
        try
        {
            Response response = Jsoup.connect(path).execute();
            cookies = response.cookies();
            Doc = response.parse();
            good = true;
        }
        catch (Exception e) 
        {
            rstring = e.getMessage().toString();
            good = false;
        } 
    }       
    return good;
}

这种方法是不正确的。我的目标是找出一种方法,在不知道哪些cookie存在的情况下,能够处理cookie的更改并保持会话。
我正在为我的Simple Machines论坛编写一个应用程序,并在点击一些自定义行为时更改其cookie配置。
但如果这个应用程序能够成功地为我的网站服务,我将发布一个版本供其他论坛使用。
我知道我正朝着正确的方向前进,但这种逻辑有点困难。
非常感谢任何建议。

除了BalusC的评论之外,p != path 的意思可能不是你真正想表达的,尽管这是可能的。 - Dave Newton
2个回答

15

这段代码非常混乱,流程不合逻辑,异常处理也很糟糕。类似于 if(p != path)if(cookys != cookies) 的对象引用比较毫无意义。若要比较对象的内容,需要使用 equals() 方法。

简单来说,我了解你想在同一域名下的一系列 Jsoup 请求中维护 cookie。在这种情况下,你需要基本上遵守以下流程:

Map<String, String> cookies = new HashMap<String, String>();

// First request.
Connection connection1 = Jsoup.connect(url1);
for (Entry<String, String> cookie : cookies.entrySet()) {
    connection1.cookie(cookie.getKey(), cookie.getValue());
}
Response response1 = connection1.execute();
cookies.putAll(response1.cookies());
Document document1 = response1.parse();
// ...

// Second request.
Connection connection2 = Jsoup.connect(url2);
for (Entry<String, String> cookie : cookies.entrySet()) {
    connection2.cookie(cookie.getKey(), cookie.getValue());
}
Response response2 = connection2.execute();
cookies.putAll(response2.cookies());
Document document2 = response2.parse();
// ...

// Third request.
Connection connection3 = Jsoup.connect(url3);
for (Entry<String, String> cookie : cookies.entrySet()) {
    connection3.cookie(cookie.getKey(), cookie.getValue());
}
Response response3 = connection3.execute();
cookies.putAll(response3.cookies());
Document document3 = response3.parse();
// ...

// Etc.

这段代码可以重构成以下方法:

private Map<String, String> cookies = new HashMap<String, String>();

public Document get(url) throws IOException {
    Connection connection = Jsoup.connect(url);
    for (Entry<String, String> cookie : cookies.entrySet()) {
        connection.cookie(cookie.getKey(), cookie.getValue());
    }
    Response response = connection.execute();
    cookies.putAll(response.cookies());
    return response.parse();
}

可用作

YourJsoupWrapper jsoupWrapper = new YourJsoupWrapper();

Document document1 = jsoupWrapper.get(url1);
// ...

Document document2 = jsoupWrapper.get(url2);
// ...

Document document3 = jsoupWrapper.get(url3);
// ...
请注意,即将发布的Jsoup 1.6.2版本将带有一个新的 Connection#cookies(Map)方法,这应该使得每次使用for循环都变得不必要。

非常感谢您。我搜索了很久,寻找正确的实现方式示例。这种方式绝对比我先前尝试的方法更好笑。 - texasman1979
来自未来的某个人!出于某种原因,我发现JSoup非常方便。我的建议是,在当前的JSoup库中有一个名为cookies(Map<String,String> cookies)的方法,它可以添加键/值对。因此,上述foreach可以替换为:connection.cookies(cookies)。 - Jose Cifuentes
您可以使用connection.cookies(cookies)代替for循环。 - caub
@crl:确实,也可以参考上面答案的最后一段和Jsoup开发者在这个答案中的评论。 - BalusC

1

+1 给 BalusC

我在你的代码中做了一些更改,现在它对我有效,所以你需要从网站获取 cookie,然后才能获取文档。

public Document get(String url) throws IOException {
    Connection connection = Jsoup.connect(url).userAgent("Mozilla/5.0 (Windows; U; WindowsNT 5.1; en-US; rv1.8.1.6) Gecko/20070725 Firefox/2.0.0.6");
    Connection.Response response = connection.execute();
    connection.cookies(response.cookies());
    return connection.get();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接