微信公众号短链实时阅读量、点赞数爬虫(不会Hook可用)
眾所周知,微信分享的公眾號分享出的一般都是短鏈,在這個鍛煉下使用瀏覽器打開并不能獲取微信公眾的閱讀量點贊數等這些信息,如圖1所示。
但是實際擁有詳細信息的則是這個鏈接下面,提取鏈接所需要提交的信息包括經過本人篩選有以下參數,并且攜帶Cookie,如圖2所示:
其中_biz、mid、sn會根據不同的文章發生變動,其余的都是固定值,但都可以從原始連接中取得,且原始鏈接可以通過F12在谷歌瀏覽器前端獲取,如圖3所示:
所以我們現在就應當編寫獲取真是鏈接代碼:
private String GetRealAddress(String url) throws IOException {
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
/// 解析html字符串
HttpResponse response = httpClient.execute(httpGet);
String html = EntityUtils.toString(response.getEntity());
Document doc = Jsoup.parse(html);
/// 獲取GET參數
String realUrl = doc.select("meta[property='og:url']").attr("content");
//獲取真實鏈接
httpClient.close();
return new URL(realUrl).getQuery();
}
根據Fiddler軟件抓包可以知道,閱讀數等詳細信息是在 https://mp.weixin.qq.com/mp/getappmsgext/...下,而要攜帶參數我們已經可以從真實長鏈中獲取。別看圖2的請求鏈接好像很長,但是實質上如果只是為了獲取閱讀量、點贊數等一些有用信息,只需要帶上appmsg_token即可,如圖4所示:
既然請求鏈接和請求參數我們都知道,那么就可以書寫代碼了:
public AjaxResponse getNumberNewWay(String url) throws IOException {
String realUrl = this.GetRealAddress(url);
if (StringUtils.hasText(realUrl)) {
// 使用分隔符 "&" 將參數字符串分割成參數對
String[] parameterPairs = realUrl.split("&");
// 創建一個 Map 來存儲參數名和參數值
Map<String, String> parameterMap = new HashMap<>();
// 遍歷參數對,提取參數名和參數值,并放入 Map 中
for (String parameterPair : parameterPairs) {
String[] parts = parameterPair.split("=");
if (parts.length == 2) {
String paramName = parts[0];
String paramValue = parts[1];
parameterMap.put(paramName, paramValue);
}
}
// 獲取各個參數的值,因為上面使用"=="分割,所以biz的值后面的“==”也會被分割
String biz = parameterMap.get("__biz") + "==";
String mid = parameterMap.get("mid");
String idx = parameterMap.get("idx");
String sn = parameterMap.get("sn");
String appmsgToken = "";
if (StringUtils.hasText(cookie)){
//獲取appmsgToken
String[] parts = cookie.split(";");
for (String part : parts) {
if (part.startsWith("appmsg_token=")) {
appmsgToken = part.substring("appmsg_token=".length());
break;
}
}
}else {
return AjaxResponse.error("cookie缺失");
}
String originUrl = "https://mp.weixin.qq.com/mp/getappmsgext?";
String postUrl = originUrl + "appmsg_token=" + appmsgToken + "&x5=0";
HttpPost httpPost = new HttpPost(postUrl);
//模擬微信客戶端
httpPost.setHeader("User-Agent", "Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0Chrome/57.0.2987.132 MQQBrowser/6.2 Mobile");
httpPost.setHeader("Cookie", cookie);
httpPost.setHeader("Origin", "https://mp.weixin.qq.com");
//httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");
CloseableHttpClient client = HttpClientBuilder.create().build();
List<NameValuePair> parameters = new ArrayList<>();
parameters.add(new BasicNameValuePair("is_only_read", "1"));
parameters.add(new BasicNameValuePair("is_temp_url", "0"));
parameters.add(new BasicNameValuePair("appmsg_type", "9"));
parameters.add(new BasicNameValuePair("__biz", biz));
parameters.add(new BasicNameValuePair("mid", mid));
parameters.add(new BasicNameValuePair("idx", idx));
parameters.add(new BasicNameValuePair("sn", sn));
HttpEntity entity = new UrlEncodedFormEntity(parameters,"utf-8");
httpPost.setEntity(entity);
// 發送請求并獲取響應
try {
HttpResponse response = client.execute(httpPost);
HttpEntity responseEntity = response.getEntity();
String StringResult = EntityUtils.toString(responseEntity);
// 創建一個 ObjectMapper 對象
ObjectMapper objectMapper = new ObjectMapper();
JsonNode jsonNode = objectMapper.readTree(StringResult);
// 提取 read_num 的值
JsonNode readJson = jsonNode.get("appmsgstat");
if (readJson != null) {
return AjaxResponse.success(readJson.get("read_num").asText());
}
return AjaxResponse.error("獲取閱讀量失敗,請檢查token是否過期");
} catch (IOException e) {
e.printStackTrace();
return AjaxResponse.error("遠程調用失敗");
}
}
return AjaxResponse.error("獲取真實地址失敗");
}
這里存在一個時效性的問題,由于微信設置的Cookie有時效性,且是由微信客戶端自身生成,并且筆者不會Hook。所以就想到了一個另類的辦法:通過定時任務刷新微信文章來刷新Cookie->利用Fidder攔截請求獲取Cookie->Cookie傳入Java代碼中獲取信息。
由于不會Hook,所以筆者就用了python的pyautogui與cv2庫識別微信瀏覽器的刷新圖標,然后定時進行刷新,大體流程是:截一張桌面圖像->識別刷新圖標位置->鼠標模擬刷新。python核心代碼如下:
def refresh_funtion():
# 截一張桌面新的圖片
newImg = pyautogui.screenshot()
newImg.save('C:\\Users\\chen\\Desktop\\newAll.png')
# 轉換為OpenCV的圖像格式
newImg_cv = cv2.cvtColor(cv2.imread('C:\\Users\\chen\\Desktop\\newAll.png'), cv2.COLOR_BGR2RGB)
# 尋找刷新按鈕
# 如果文本框已經打開則進行刷新
refreshTemplate = cv2.imread('C:\\Users\\chen\\Desktop\\refresh.jpg')
# 在屏幕截圖中搜索目標圖像
refreshRes = cv2.matchTemplate(newImg_cv, refreshTemplate, cv2.TM_CCOEFF_NORMED)
# 獲取匹配度最高的位置
refresh_min_val, refresh_max_val, refresh_min_loc, refresh_max_loc = cv2.minMaxLoc(refreshRes)
# 如果存在則刷新
# 如果匹配度最高的位置的閾值大于 0.8,則模擬鼠標點擊
if refresh_max_val > 0.8:
# 計算鼠標點擊的位置
x, y = refresh_max_loc[0] + refreshTemplate.shape[1] // 2, refresh_max_loc[1] + refreshTemplate.shape[0] // 2
# 模擬鼠標點擊
pyautogui.click(x, y)
這里就需要使用FiddlerScript腳本,在Fiddler軟件的FidderScipt中的OnBeforRequest方法內插入圖5中代碼,將刷新的Cookie傳遞到Java代碼中,再讓Java代碼根據傳遞到的Cookie解析并獲取微信信息,如圖5所示:
?
本方法僅提供不會Hook的同學的權宜之計,僅供學習參考使用,不可用于違法途徑。
總結
以上是生活随笔為你收集整理的微信公众号短链实时阅读量、点赞数爬虫(不会Hook可用)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转载】小公司如何留住技术人才?
- 下一篇: 沉默的螺旋--digest