<<上篇 | 首页

Fix certificate problem in HTTPS - Real's Java How-to

HTTPS protocol is supported since JDK1.4 (AFAIK), you have nothing special to do.

import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;

public class ConnectHttps {
  public static void main(String[] args) throws Exception {
    URL url = new URL("https://securewebsite.com");
    URLConnection con = url.openConnection();
    Reader reader = new InputStreamReader(con.getInputStream());
    while (true) {
      int ch = reader.read();
      if (ch==-1) {
        break;
      }
      System.out.print((char)ch);
    }
  }
}

However, you can have a problem if the server certificate is self-signed by a testing certification authority (CA) which is not in trusted CAs of Java on the client side. An exception like

Exception in thread "main" javax.net.ssl.SSLHandshakeException:
  sun.security.validator.ValidatorException:
    PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
      unable to find valid certification path to requested target

is thrown. This is a common situation with a development server.

The fix is to add the self signed certificate to trusted CAs on the client side. You do that by updating the CACERT file in the your JRE_HOME/lib directory.

Check this tutorial : http://www.java-samples.com/showtutorial.php?tutorialid=210

Or you can override the check and accept an untrusted certificate (with the risk coming with it!).

import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URL;
import java.net.URLConnection;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.cert.X509Certificate;

public class ConnectHttps {
  public static void main(String[] args) throws Exception {
    /*
     *  fix for
     *    Exception in thread "main" javax.net.ssl.SSLHandshakeException:
     *       sun.security.validator.ValidatorException:
     *           PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException:
     *               unable to find valid certification path to requested target
     */
    TrustManager[] trustAllCerts = new TrustManager[] {
       new X509TrustManager() {
          public java.security.cert.X509Certificate[] getAcceptedIssuers() {
            return null;
          }

          public void checkClientTrusted(X509Certificate[] certs, String authType) {  }

          public void checkServerTrusted(X509Certificate[] certs, String authType) {  }

       }
    };

    SSLContext sc = SSLContext.getInstance("SSL");
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

    // Create all-trusting host name verifier
    HostnameVerifier allHostsValid = new HostnameVerifier() {
        public boolean verify(String hostname, SSLSession session) {
          return true;
        }
    };
    // Install the all-trusting host verifier
    HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
    /*
     * end of the fix
     */

    URL url = new URL("https://securewebsite.com");
    URLConnection con = url.openConnection();
    Reader reader = new InputStreamReader(con.getInputStream());
    while (true) {
      int ch = reader.read();
      if (ch==-1) {
        break;
      }
      System.out.print((char)ch);
    }
  }
}
 

阅读全文……

标签 : ,

爬取百度网盘用户分享 | Guodong

上面3个连接请求必须带上 ("Referer", "https://yun.baidu.com/share/home?uk=23432432#category/type=0"),uk多少无所谓,否则请求不到json数据,
获取用户订阅和获取用户粉丝每次请求一次休眠2s的话可以无限制请求,对ip没要求,获取用户分享超坑,一个ip只能请求10次,并且休眠也没用.
因为没有那么多ip,我就去研究手机版的用户分享,手机版获取用户分享可以一次性连续请求60次,60次后必须休眠35s左右在继续请求就可以,不会像pc版那样必须换ip,
但是手机版只能请求网页源码,然后用正则进行匹配.

下面上源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
private Logger log = LoggerFactory.getLogger(FollowStartIndex.class);
public void startIndex() {
//无限循环
while (true) {
//从数据库获取可用uk,可用首先从某个粉丝超多的用户入手,获取他粉丝的uk,存入数据库
Avaiuk avaiuk = Avaiuk.dao.findFirst("select * from avaiuk where flag=0 limit 1");
//更新数据库,标记该uk已经被用户爬过
avaiuk.set("flag", 1).update();
getFllow(avaiuk.getLong("uk"), 0);
}
}

static String url = "http://yun.baidu.com/pcloud/friend/getfollowlist?query_uk=%s&limit=24&start=%s&bdstoken=e6f1efec456b92778e70c55ba5d81c3d&channel=chunlei&clienttype=0&web=1&logid=MTQ3NDA3NDg5NzU4NDAuMzQxNDQyMDY2MjA5NDA4NjU=";
static Map map = new HashMap();

static {
map.put("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36");
map.put("X-Requested-With", "XMLHttpRequest");
map.put("Accept", "application/json, text/javascript, */*; q=0.01");
map.put("Referer", "https://yun.baidu.com/share/home?uk=325913312#category/type=0");
map.put("Accept-Language", "zh-CN");
}

//获取订阅用户
public void getFllow(long uk, int start, boolean index) {
log.info("进来getFllow,uk:{},start:{}", uk, start);
boolean exitUK = false;
try {
exitUK = Redis.use().exists(uk);
} catch (Exception e) {
exitUK = true;
}
if (!exitUK) {
Redis.use().set(uk, "");
if (index) {
indexResource(uk);
}
recFollow(uk,start,true);
} else {
if (start > 0) {//分页订阅
recFollow(uk,start,false);
} else {
log.warn("uk is index:{}", uk);
}
}


}
public void recFollow(long uk,int start,boolean goPage){
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String real_url = String.format(url, uk, start);
ResponseBody body = OkhttpUtil.syncGet(real_url, Headers.of(map));
if (body != null) {
try {
Follow follow = JSON.parseObject(body.string(), Follow.class);

if (follow.getErrno() == 0) {
List<Follow.FollowListBean> followListBeen = follow.getFollow_list();
if (followListBeen != null && followListBeen.size() > 0) {
log.info("不为空:{}", follow);
for (Follow.FollowListBean bean : followListBeen) {
int follow_count = bean.getFollow_count();
int shareCount=bean.getPubshare_count();
if (follow_count > 0) {
if (shareCount > 0) {
getFllow(bean.getFollow_uk(), 0, true);
} else {
getFllow(bean.getFollow_uk(), 0, false);
}
}
}
if(goPage){
int total_count = follow.getTotal_count();
//log.warn("分页页数:{}",total_count);
//分页
int total_page = (total_count - 1) / 24 + 1;

for (int i = 1; i < total_page; i++) {
getFllow(uk, i * 24,false);
}

}
} else {
log.info("为空:{}", follow);
}
}

} catch (IOException e) {
e.printStackTrace();
}
}
}

long uinfoId = 0;
long nullStart = System.currentTimeMillis();

public void indexResource(long uk) {
while (true) {
String url = "http://pan.baidu.com/wap/share/home?uk=%s&start=%s&adapt=pc&fr=ftw";
String real_url = String.format(url, uk, 0);

YunData yunData = DataUtil.getData(real_url);

if (yunData != null) {
log.info("{}", yunData.toString());
int share_count = yunData.getUinfo().getPubshare_count();
if (share_count > 0) {
Uinfo uinfo = new Uinfo();
uinfo.set("uname", yunData.getUinfo().getUname()).set("avatar_url", yunData.getUinfo().getAvatar_url()).set("uk", uk).set("incache", 1).save();
uinfoId = uinfo.getLong("id");
List<Records> recordses = yunData.getFeedata().getRecords();
for (Records record : recordses) {
new ShareData().set("title", record.getTitle()).set("shareid", record.getShareid()).set("uinfo_id", uinfoId).save();
}

}
int totalPage = (share_count - 1) / 20 + 1;

int start = 0;
if (totalPage > 1) {
for (int i = 1; i < totalPage; i++) {
start = i * 20;
real_url = String.format(url, uk, start);
yunData = DataUtil.getData(real_url);
if (yunData != null) {
log.info("{}", yunData.toString());
List<Records> recordses = yunData.getFeedata().getRecords();
for (Records record : recordses) {
//用户分享的数据存入数据库
new ShareData().set("title", record.getTitle()).set("shareid", record.getShareid()).set("uinfo_id", uinfoId).save();
}
} else {
i--;
log.warn("uk:{},msg:{}", uk, yunData);
long temp = nullStart;
nullStart = System.currentTimeMillis();
if ((nullStart - temp) < 1500) {
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}

}

}
break;
} else {
log.warn("uk:{},msg:{}", uk, yunData);
long temp = nullStart;
nullStart = System.currentTimeMillis();
//在1500毫秒内2次请求到的数据都为null时,此时可能被百度限制了,休眠一段时间就可以恢复
if ((nullStart - temp) < 1500) {
try {
Thread.sleep(60000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}


}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
public class DataUtil {
public static YunData getData(String url) {
//自己对okhttp的封装
ResponseBody body = OkhttpUtil.syncGet(url);
String html = null;
if (body == null) {
return null;
}
try {
html = body.string();
} catch (IOException e) {
return null;
}
Pattern pattern = Pattern.compile("window.yunData = (.*})");
Matcher matcher = pattern.matcher(html);
String json = null;
while (matcher.find()) {
json = matcher.group(1);
}
if (json == null) {
return null;
}
//fastjson
YunData yunData = JSON.parseObject(json, YunData.class);
return yunData;
}
}

YunData自己获取下json数据,就能创建出来,代码就不放了.

这么爬取速度很快,3台服务器一天就爬取了100多万.
Golang版本

阅读全文……

标签 : , ,

《搜索引擎评分指南》阅读心得

#《搜索引擎评分指南》阅读心得  

##1、 搜索词的三种分类  
搜索引擎把搜索词分为三类:Know,Do和Go,以下是关于三类搜索的简单解释:

*   Know,信息性搜索,这类用户想要了解某些信息,如“南京五一天气怎样”,“南京五一有哪些地方好玩”等。
*   Do,事务型搜索,这类用户想要完成某个目标或参与某个网上活动。他的目标可能是下载,购买,娱乐等,比如“美图秀秀下载”,“植物大战僵尸online”,“cheap mp3 player”等。  
*   Go,导航型搜索,这类用户是要到达某个特定网页,比如“中国制造网”,“优酷”,“新浪微博”等。  

另外,很多搜索词会有不止一种用户意图,比如“ipad”,用户可能想要ipad的简介(Know型),可能想要到达ipad的官网页面(Go型),也可能是想要购买ipad(Do型)。
**搜索词分类的作用很多,可自行扩展。下面简单列举了2种:**

*   便于关键词分析。将关键词按用户意图区分,可以更了解这些关键词背后的含义,有利于对关键词做更好的布局。
*   方便关键词拓展。可以根据关键词的3种分类去对照自身网站,看是否有关键词拓展的空间。

**注:**
关键词分类对电商类网站尤其重要,比如电商类要将事务型搜索关键词作为网站转化的重点;还有淘宝客,可以说最核心的就是如何找到转化率高的长尾关键词;我之前工作过的医疗网站也是,寥寥几个事务型关键词(多为地区类病种词)几乎可以占据每天转化量的一半。




##2、用户意图  
之前一直以为影响网页排名的只有2个因素:**网页与搜索词的相关性**和**网页的重要性**。看了文档才知道有个更高级的因素,那就是**用户意图**。其实也很容易理解:搜索引擎的目的就是满足用户的搜索需求,因此搜索引擎会先根据**用户搜索词**判断**用户意图**(简单分为Do,Go和Know型),然后给出符合需求的一类网页,接着才会根据相关性和重要性对这一类页面进行排序。
例如用户搜索”宫保鸡丁“,而我有个网页是”宫保鸡丁的来历“,虽然我的网页相关性很强(关键词位置,密度,内外链等),也有很多高质量外链,但考虑到搜索这个词的大多数用户都想要知道”宫保鸡丁的做法“,只有极少数是想了解”宫保鸡丁的来历“,所以第一步就落后了,之后也不太可能有很好的排名。除非用户搜索”宫保鸡丁的来历“,这个网页因为很符合用户的需求,排名才会靠前。
也就是说,**要想让某个关键词的排名靠前,首先要分析这个关键词,了解搜索这个关键词的用户想要得到什么信息,然后根据用户需求去组织页面,这样才可能获得理想排名**。也就是说,如果网页是”宫保鸡丁的来历“,那还是不要把精力放在”宫保鸡丁“这个排名上了,因为匹配度太低了。 
**注:**
这东西说来很虚,但用户和搜索引擎都喜欢,可以看看夜息哥哥这篇文章http://www.imyexi.com/?p=853,花很大精力搞卡片分拣就只是为了满足用户需求,在侧边栏放上用户需要的链接。这些链接虽然不起眼,但想想如果有成千上万个页面都放上了用户更感兴趣的链接,那效果就不可同日而语,这其实也是产品,运营,体验的工作。


##3、 网页评级
谷歌根据用户意图与页面的匹配程度,将搜索结果分为5种类型:**至关重要型**,**实用型**,**相关型**,**基本相关型**与**离题或无价值型**。

*   至关重要型。一个页面可以满足用户的所有搜索意图,多用于导航型搜索。  
*   实用型。页面质量高,可满足大多数用户的需求。  
*   相关型。跟搜索需求相匹配,可以满足部分用户的需求。  
*   基本相关型。对大多数用户不那么有价值,但多少跟搜索需求相关。  
*   离题或无价值型。跟搜索请求不匹配,或者没有实际价值,对绝大多数用户没有帮助。

结合**用户意图**的解释可以得到2点:  
1.  只有符合用户意图,满足用户主体需求的页面,评级才会高,排名才会靠前。比如搜索”宫保鸡丁“时为什么”宫保鸡丁的来历“排名较低,因为他没有满足搜索者的主体需求,只是跟搜索词算是**基本相关**。
2.  如果页面内容与关键词匹配度不高,评级低,无法获得很好的排名。例如“宫保鸡丁的来历”想要获得“宫保鸡丁”的排名。

**注:**
相对于用户意图,那些关键词密度,H标签什么的简直弱爆了。

##4、 关键词堆砌  
谷歌对关键词堆砌的分类:  

*   关键词在页面上重复多次  
*   关键词的相关词在页面上重复多次  
*   关键词的拼写错误在页面上重复多次  
*   页面上存在大量胡乱的随机的关键词
*   页面上存在大量程序自动生成的文本,并没有任何意义。  

谷歌对关键词堆砌的处理方式:当页面上关键词数量过多,干扰了用户的正常访问,那就会认定为关键词堆砌;而如果没有察觉到关键词数量的影响,那将不被认为是堆砌。  

**注:**
有时候我们把搜索引擎想象的太弱智了,不是吗?!



##5、 对网页语言的判断  

谷歌已有很成熟的技术去判断网页语言,而不仅仅依靠HTTP响应头部的Charset和Content-Language。比如Google Translate的API里就有相应的功能,能识别网页的语言。(具体可以看<a href="https://developers.google.com/translate/v2/getting_started?hl=zh-CN">谷歌翻译API</a>里的detect source language一项。)  
也就是说,**如果Charset和Content-Language设置为中文,不一定会被谷歌认为是中文网页,只是会干扰谷歌的判断**。  
另外,这不表示Charset和Content-Language设置错误没有影响,Charset和Content-Language的合理设置会让网页更加规范,也避免了用户在浏览网页时弹出其他字符集下载。
 

阅读全文……

标签 :