微博爬蟲基礎篇——簡單的微博爬蟲(手動cookie)

 

一、前言

博客,這東西寫起來是真的麻煩。博主語文特不好,什麼語句、語義不通之類的,是常有的。請務必不要在意。如果,有什麼問題可以在底下留言,或者私信我索要聯繫方式。另外,博主常年混跡java吧,在那肯定能找到我,貼吧ID:ZSsanguosha 。 轉載,保留“全屍”就可以了,標明出處和作者,,其餘隨意。以上

博主郵箱的綁定了數據庫預警系統,一響就代表採集系統崩了,已經響出陰影了。所以別問我要郵箱。

最後,本篇講的是微博爬蟲的基礎實現,適用範圍:小規模使用

二、原理

微博有一個“Sina Visitor System”(新浪訪客系統),如果沒有專門的微博cookie,所有請求都會被這個系統攔截。反過來說,只要獲取到這個cookie,就能爬取到微博的頁面。

類似的教程網上有很多,但其實有很多教程,一些細節(注意事項)都沒有講清楚,所以,我特意整理一下。

三、實現

爬蟲,博主推薦用python實現,不過在這裏,博主選用java給大家演示。因爲博主以前已經用java實現過一遍,ctrl+cv就行,實在不想再寫一遍。

接下來,就是實戰。這次選用的是微博的榜單頁面(https://d.weibo.com/1087030002_2975_2017_0)

獲取cookie: 先登錄微博。然後谷歌瀏覽器,F12打開開發者,ctrl+R刷新請求,找到當前頁面的請求,複製cookie。

1、依賴

本次選用的是 請求工具是httpclient,解析頁面是 jsoup

<dependency>
  	<groupId>org.jsoup</groupId>
  	<artifactId>jsoup</artifactId>
  	<version>1.10.1</version>
</dependency>
<dependency>
  	<groupId>org.apache.httpcomponents</groupId>
  	<artifactId>httpclient</artifactId>
  	<version>4.5.5</version>
</dependency>

2、模擬請求,獲取html

創建get請求,設置請求頭,模擬真實用戶。將上圖的請求頭信息,複製進來,即可

微博的大部分頁面都是get請求,這些請求頭其實只要設置"user_agent"和“host”還有“cookie” 就可以了,其餘可要不可不要

csdn的排版不怎麼熟悉,可能是因爲太長了,實在太醜,所以有些代碼是截圖的

httpHost 是用來設置代理的,不需要可以填入null

private RequestConfig getRequestConfig() {
    return RequestConfig.custom().setSocketTimeout(3000).setConnectTimeout(3000)
                .setConnectionRequestTimeout(3000)
	        .setProxy(httpHost).build();
}

 博主在中間加了一步驗證。主要是因爲,微博爬蟲,時不時會因爲各種問題出現各種錯誤以及各種錯誤界面,光用響應代碼是不好控制的,所以加一步響應內容的校驗。

for循環是爲了排除網絡問題導致的爬取失敗

“empty_con clearfix”是目標頁面的某個標籤id,“follow_item S_line2”是某個錯誤頁面的

private String get(HttpGet httpGet) {
  //設置返回內容的檢測邏輯
  Predicate<String> predicate = s -> (s == null || "".equals(s))
  		|| s.contains("empty_con clearfix") || !s.contains("follow_item S_line2");
  return get(httpGet, predicate);
}
	
private String get(HttpGet httpGet, Predicate<String> predicate) {
  //最多重試5次				
  for(int i=0;i<5;i++) {
  	try {
		CloseableHttpResponse response = httpclient.execute(httpGet);
		HttpEntity httpEntity = response.getEntity();
		String responseContent = getResponseContent(httpEntity);
		//雙重判斷				
		if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK
				&& !predicate.test(responseContent))
		{
			return responseContent;
		}
	}
	catch (Exception e) {
		sleep(3000L);
	}
  }		
  return null;
}

至此,我們已經獲取到了頁面的html,接下來,是解析數據。不過要注意,微博的頁面數據是用FM.view()填充的,所以需要進行處理。下面,是我以前寫的解析例子,至今還是可以用的

/**
 * @Title: parseData 
 * @Description: TODO(解析頁面數據轉化爲集合) 
 * @param html
 * @param domain
 * @return
 *     List<WeiboDomainGroup> 返回類型
 */
public List<WeiboDomain> parseData(String html){
	List<WeiboDomain> result = new ArrayList<>();
	Document doc = Jsoup.parse(html);
	//處理填充數據
	String str = "";
	Elements scripts = doc.getElementsByTag("script");
	//找到包含數據的script			
	for (int i=0;i<scripts.size();i++) {
		String script = scripts.get(i).html();
		if (script.contains("pl.content.signInPeople.index")) {
			str = getHtml(script);
			break;
		}
	}
	
	//解析頁面數據
	doc = Jsoup.parse(str);
	Elements user = doc.getElementsByTag("dd");
	for (Element element : user){
		if (element.attr("class").equals("mod_info S_line1"))	{
    		WeiboDomain weiboDomainGroup = new WeiboDomain();
			String uid = "";
			Elements elements = element.getElementsByTag("div");
			for (Element div : elements){
				if (div.attr("class").equals("info_name W_fb W_f14")){
					Element S_txt1 = div.getElementsByClass("S_txt1").get(0);
					uid = S_txt1.attr("usercard").split("&")[0].replaceAll("id=", "");
					weiboDomainGroup.setUid(uid);
					weiboDomainGroup.setUrl(S_txt1.attr("href"));
					weiboDomainGroup.setName(S_txt1.attr("title"));
					
					Elements i = div.getElementsByTag("i");
					for (Element ele : i){
						if (ele.attr("class").equals("W_icon icon_member")){
							weiboDomainGroup.setVip(true);
						}
						if (ele.attr("class").equals("W_icon icon_male")){
							weiboDomainGroup.setGender("m");
						}
						else{
							weiboDomainGroup.setGender("f");
						}
					}
				}
				if (div.attr("class").equals("info_connect"))	{
					Elements em = div.getElementsByTag("em");
	       		    weiboDomainGroup.setFriends_count(
                        Integer.parseInt(em.get(0).text()));
					weiboDomainGroup.setFollowers_count(em.get(1).text());
					weiboDomainGroup.setStatuses_count(
                        Integer.parseInt(em.get(2).text()));
				}
				if (div.attr("class").equals("info_add")){
					Elements span = div.getElementsByTag("span");
					weiboDomainGroup.setLocation(span.get(0).text());
				}
				if (div.attr("class").equals("info_intro")){
					Elements span = div.getElementsByTag("span");
					weiboDomainGroup.setDescription(span.get(0).text());
				}
				if (div.attr("class").equals("info_relation")){
					String tag = div.text().split(":")[1];
					weiboDomainGroup.setTag(tag);
				}
			}
			weiboDomainGroup.setUpdateTime(LocalDateTime.now()
					.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
			result.add(weiboDomainGroup);
		}
    }	
	return result;
}
	
/**
 * @Title: getHtml 
 * @Description: TODO(微博數據是用FW.view填充,所以需要解析) 
 * @return
 *     String 返回類型
 */
private String getHtml(String str) {
	str = str.replaceAll("FM.view\\(", "").replaceAll("\\)", "");
	JSONObject json = JSONObject.fromObject(str);
	return json.getString("html");
}

實體類

/** 
 * @ClassName: entity 
 * @Description: TODO(這裏用一句話描述這個類的作用) 
 * @date 2018年2月23日 下午2:37:27  
 */
@Data
public class WeiboDomain {
	private String uid;
	private String name;
	private String url;
	private String gender;
	private String location;
	private String description;
	private String tag;
	private String followers_count;
	private Integer friends_count;
	private Integer statuses_count;
	private boolean isVip;
	private String updateTime;
}

最後,我們稍微測試下,準確無誤。 over 

四、注意事項

 1、截止2018年7月31日 23:02:05。 代碼可用

 2、該方法適用於小規模需求,比如爬某幾個賬號的微博內容、點贊、轉發數。且無法實現自動化

 3、cookie具有時效性,過期時間好像是12個小時?

 4、cookie中帶有賬號信息,爬取太多次可能會被封賬號

五、模擬登錄

以上的方法是不可以實現自動化,但是我們,可以通過模擬登錄獲取cookie,實現自動化。本來是這樣,不過,博主今天測試的時候發現自己以前寫的模擬登錄,已經不可用了。博主後面會講怎麼用另一種方法自動獲取cookie。所以,這方面大家自己找資料吧,博主也就不修復了

六、代碼

代碼已經上傳到csdn(https://download.csdn.net/download/qq_41057280/10575744),需要可自行下載。如果沒有積分的話,可以聯繫博主,聯繫方式開頭寫了

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章