Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/384.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
403禁止使用Java但不使用web浏览器?_Java_Http Status Code 403 - Fatal编程技术网

403禁止使用Java但不使用web浏览器?

403禁止使用Java但不使用web浏览器?,java,http-status-code-403,Java,Http Status Code 403,我正在编写一个小型Java程序,以获取给定Google搜索词的结果量。出于某种原因,在Java中我得到了403,但在web浏览器中我得到了正确的结果。代码: import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; public class DataGetter { public static void main(

我正在编写一个小型Java程序,以获取给定Google搜索词的结果量。出于某种原因,在Java中我得到了403,但在web浏览器中我得到了正确的结果。代码:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;


public class DataGetter {

    public static void main(String[] args) throws IOException {
        getResultAmount("test");
    }

    private static int getResultAmount(String query) throws IOException {
        BufferedReader r = new BufferedReader(new InputStreamReader(new URL("https://www.google.com/search?q=" + query).openConnection()
                .getInputStream()));
        String line;
        String src = "";
        while ((line = r.readLine()) != null) {
            src += line;
        }
        System.out.println(src);
        return 1;
    }

}
错误是:

Exception in thread "main" java.io.IOException: Server returned HTTP response code: 403 for URL: https://www.google.com/search?q=test
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
    at DataGetter.getResultAmount(DataGetter.java:15)
    at DataGetter.main(DataGetter.java:10)

为什么要这样做?

您可能没有设置正确的标题。在浏览器中使用
LiveHttpHeaders
(或等效项)查看浏览器正在发送哪些标头,然后在代码中模拟这些标头。

这是因为站点使用SSL。尝试使用Jersey HTTP客户端。您可能还需要了解一些关于HTTPS和证书的知识,但我认为Jersey可以设置为忽略与实际安全性相关的大部分细节。

您只需设置user agent header即可使其工作:

URLConnection connection = new URL("https://www.google.com/search?q=" + query).openConnection();
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
connection.connect();

BufferedReader r  = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charset.forName("UTF-8")));

StringBuilder sb = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
    sb.append(line);
}
System.out.println(sb.toString());
从异常stacktrace可以看出,SSL是透明地为您处理的

但是,获取结果量并不是那么简单,在此之后,您必须通过获取cookie并解析重定向令牌链接来假装自己是浏览器

String cookie = connection.getHeaderField( "Set-Cookie").split(";")[0];
Pattern pattern = Pattern.compile("content=\\\"0;url=(.*?)\\\"");
Matcher m = pattern.matcher(response);
if( m.find() ) {
    String url = m.group(1);
    connection = new URL(url).openConnection();
    connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
    connection.setRequestProperty("Cookie", cookie );
    connection.connect();
    r  = new BufferedReader(new InputStreamReader(connection.getInputStream(), Charset.forName("UTF-8")));
    sb = new StringBuilder();
    while ((line = r.readLine()) != null) {
        sb.append(line);
    }
    response = sb.toString();
    pattern = Pattern.compile("<div id=\"resultStats\">About ([0-9,]+) results</div>");
    m = pattern.matcher(response);
    if( m.find() ) {
        long amount = Long.parseLong(m.group(1).replaceAll(",", ""));
        return amount;
    }

}
String cookie=connection.getHeaderField(“Set cookie”).split(“;”)[0];
Pattern=Pattern.compile(“content=\\\”0;url=(.*?\\”);
匹配器m=模式匹配器(响应);
if(m.find()){
字符串url=m.group(1);
连接=新URL(URL).openConnection();
setRequestProperty(“用户代理”、“Mozilla/5.0(Windows NT 6.1;WOW64)AppleWebKit/537.11(KHTML,类似Gecko)Chrome/23.0.1271.95 Safari/537.11”);
setRequestProperty(“Cookie”,Cookie);
connection.connect();
r=新的BufferedReader(新的InputStreamReader(connection.getInputStream(),Charset.forName(“UTF-8”));
sb=新的StringBuilder();
而((line=r.readLine())!=null){
某人附加(行);
}
response=sb.toString();
pattern=pattern.compile(“关于([0-9,]+)结果”);
m=模式匹配器(响应);
if(m.find()){
long amount=long.parseLong(m.group(1.replaceAll)(“,”,”);
退货金额;
}
}

运行时,我得到了
29300000L

对我来说,它通过添加标题起作用:
“接受”:“*/*”

我尝试了
”https://www.google.com/search?q=“+query+”&rlz=1c1rnn_enUS371&aq=f&oq=“+query+”&sugexp=chrome,mod=6&sourceid=chrome&ie=UTF-8”
,仍然没有work@PicklishDoorknob您添加了一个查询字符串参数,但没有更改标题。您可以在
URLConnection
object上使用
.setRequestProperty()
设置标题这里有一篇关于添加请求标题的SO文章:@Perception um。。。什么是SSL端点?(对不起,我对这类东西一无所知)SSL(安全套接字层)是一种确保客户机和服务器之间来回传递的数据安全的方法。SSL端点是常规URL,但使用https而不是http。使用SSL比常规http更复杂,因为客户端和服务器之间需要握手。在您的情况下,这是不必要的,因为您可以使用Google的“普通”http端点(http;//www.Google.com/search)@Perception,如果我使用普通的http://同样的事情发生了添加您正在处理的查询。不,不是,它只是通过模拟浏览器http头来工作,就像@KevinDay在他的回答中说的那样。@Ben Brunk-这里有一个很好的教训-在核心,所有的编程都是由一层又一层的附加抽象构建的。理解低层次是非常有用的。使用像您描述的更高级别的客户机可能会起作用,但这只是因为这是一个低级别的呼叫,如果您选择的话,您自己也可以进行。我永远不会忘记,坐下来使用telnet客户端与web服务器交互并手工制作HTTP请求对我来说是多么有启发性。干杯!事实上,我仍然不知道为什么该代码会起作用,因为您通常必须将站点的公共证书添加到您的本地Java密钥库中,以便像这样使用SSL,即使使用URLConnection,因此该URL也不起作用。还有,是什么让你认为我从未使用telnet连接过网站?我这样做是为了谋生,我经常忘记这个网站上有很多人是学生或业余程序员。我只是试着保持高效。如果网站使用一个证书,该证书与它的cacerts truststore(位于jdk\jre\lib\security)中的JAVA包含的CA有一个信任链,那么不需要显式添加网站证书。伙计,我欠你一桶啤酒,这是解决我问题的完美方法!谷歌能用这个方法限制/限制你的搜索结果吗?@gudthing throttling是基于ip的,所以它不是关于这个方法,而是关于你是否改变你的ip:-)我明白了!简单的路由器重启(用于WAN更改)将解决问题:)。再次感谢!!connection.connect();将抛出异常“已连接”@Esailija变量
response
应该包含什么?这对我来说很有效,但我不确定它为什么有效。你能解释一下吗?