【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>
1.问题起因
公司太小,居然让我一个后端去写前端代码,心痛。
更恶心的是,老板要求我写一个天气展示的插件,要求和百度一模一样。
天可怜见呀,我看着前端代码首先就反胃,让我写前端,你不如杀了我。
但是无可奈何,我又不敢辞职,只能硬着头皮上了。
但是能力实在有限,左思右想下,下定决心,干脆把百度天气页面爬下来,截取其中的天气插件部分。 于是乎,后台写了一个爬虫,前端页面读取后台,后台请求百度,并缓存一分钟。
(大家千万别学我,万一哪天百度改了这个插件,你会发现你要完蛋了)
结果是非常成功,做的和百度分毫不差(百度的天气插件真的不错),然而悲催的事情来了。今天我看这个天气页面的时候发现时间居然是上周的时间,顿时感觉不妙。
2. 原因分析
我通过wireshark看到请求结果,返回的是上周的天气。 并且我在服务器上直接curl返回的是上周天气,而本地则返回当前时间的天气
由此我做一下猜测。
百度对服务器的ip做了缓存,当服务器请求"深圳天气"时,就会返回缓存页面。
这下可把我搞吐血了,我做出大量实验
3.方案
方案1:
前端直接去请求百度页面,然后对页面剪裁。
然而,不管是script还是iframe,全部告知跨域(跨域真的是毒瘤)
方案2:
后台去搞ip代理,但是国外的ip直接会被百度拦下来,而国内的代理ip慢死人。简直不要太烦了。
只有收费的ip代理才勉强可以用,但是想想老板的表情,我就知道不现实。
方案3: 改user-agent,然后并没有什么用。
4. 最终方案
我本地在搜索“深圳天气”的时候,灵机一动,如果我加上“深圳天气2019年12月19日”那不是可以相当于搜索不同的关键字,是不是能够绕过百度的缓存?
于是我丢上服务器了,结果更头疼了,我发现搜索““深圳天气2019年12月19日” 服务器检索出来的页面没有带上 百度的天气插件,而我本地却带上了,也就是说只有搜索“深圳天气”服务器才会带上天气插件。
但是这并没有难倒我,我知道百度搜索肯定会去掉我输入的关键字中没用的部分,如“。??”等,那么如果我的关键字带上这些没用的字符,如"深圳天气.??。。?"等,能够干掉缓存吗?
然后我写了一段代码。
private static final String[] confusion={"。","?","?","/"};
private static String getQueryParam(){
//防止百度和谐
int len = (int)(Math.random()*10+1);
StringBuilder sb = new StringBuilder("深圳天气");
for (int i=0;i<len;i++){
sb.append(confusion[(int)(Math.random() * confusion.length)]);
}
String wd = null;
try {
wd = URLEncoder.encode(sb.toString(), "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println(wd);
return wd;
}
丢上了服务器,果然起作用了,百度这下无法对我的ip缓存了。
由此得出一个结论:你长时间以某种"高"频率访问百度的同一个关键字,百度是会把你的ip和关键字绑定做缓存的。想要破除这种缓存,可以从关键字入手,加上一些无用的字符,这种字符不会参与检索。
来源:oschina
链接:https://my.oschina.net/lianghao0/blog/3145102