C# 今日头条as,cp 算法
网上找了下全是PHP或者JS 的,自己写了个C#的:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
namespace WpfApplication1
{
public class ToutiaoASCP
{
/*
* auther : wgscd
* date: 2018-4-28
*/
//https://www.toutiao.com/c/user/article/?page_type=1&user_id=58865304456&max_behot_time=1520622925&count=20&as=A1554AEA1B13257&cp=5AABC3D275071E1&_signature=wQ7S9xAbm68jAWE21IUZHsEO0u
/*
js CODE:
function getAsCp()
{
$as = ''; $cp = '';
$time = time();
$key = strtoupper(dechex($time));
$md5Key = strtoupper(md5($time));
if (8 !== strlen($key)) {
$as = '479BB4B7254C150';
$cp = '7E0AC8874BB0985';
} else {
$md5KeyAsc5 = substr($md5Key, 0, 5);
$md5KeyDesc5 = substr($md5Key, -5);
$as = ''; $cp = '';
for ($i = 0; $i < 5; $i ++) {
$as .= $md5KeyAsc5[$i] . $key[$i];
$cp .= $key[$i + 3] . $md5KeyDesc5[$i];
}
$as = 'A1' . $as . substr($key, -3);
$cp = substr($key, 0, 3) . $cp . 'E1';
}
return array($as, $cp);
*/
public static string generateASCP() { string AS = ""; string CP = ""; string md5KeyAsc5 = ""; string md5KeyDesc5 = ""; long time = Timestamp(); string key = time.ToString("X2").ToUpper(); string md5Key = EncryptWithMD5("" + time).ToUpper(); if (8 != key.Length) { AS = "479BB4B7254C150"; CP = "7E0AC8874BB0985"; } else { md5KeyAsc5 = md5Key.Substring(0, 5); md5KeyDesc5 = md5Key.Substring(md5Key.Length - 5); AS = ""; CP = ""; for (int i = 0; i < 5; i++) {
AS += md5KeyAsc5[i].ToString() + key[i].ToString();
CP += key[i + 3].ToString() + md5KeyDesc5[i].ToString();
} AS = "" + "A1" + AS + key.Substring(key.Length - 3); CP = key.Substring(0, 3) + CP + "E1"; } return "as=" + AS + "&cp=" + CP; } /// <summary> /// 当前时间戳 /// </summary> /// <returns></returns> static long Timestamp() { System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 当地时区 long timeStamp = (long)(DateTime.Now - startTime).TotalSeconds; // 相差秒数 System.Console.WriteLine(timeStamp); return timeStamp; } /// <summary> /// 时间戳转日期 /// </summary> /// <param name="time"></param> /// <returns></returns> static DateTime TimestampToDatetime(long time) { long unixTimeStamp = 1478162177; System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); // 当地时区 DateTime dt = startTime.AddSeconds (unixTimeStamp); System.Console.WriteLine(dt.ToString("yyyy/MM/dd HH:mm:ss:ffff")); return dt; } static string EncryptWithMD5(string source) { byte[] sor = Encoding.UTF8.GetBytes(source); MD5 md5 = MD5.Create(); byte[] result = md5.ComputeHash(sor); StringBuilder strbul = new StringBuilder(40); for (int i = 0; i < result.Length; i++) { strbul.Append(result[i].ToString("x2"));//加密结果"x2"结果为32位,"x3"结果为48位,"x4"结果为64位 } return strbul.ToString(); } } }
转载个JAVA的:
public class ToutiaoUtil { /** * 生成 as 和 cp , 用作 API 的请求参数 * <p> * function () { * var t = Math.floor((new Date).getTime() / 1e3), i = t.toString(16).toUpperCase(), e = md5(t).toString().toUpperCase(); * if (8 != i.length)return {as: "479BB4B7254C150", cp: "7E0AC8874BB0985"}; * for (var s = e.slice(0, 5), o = e.slice(-5), n = "", a = 0; 5 > a; a++)n += s[a] + i[a]; * for (var l = "", r = 0; 5 > r; r++)l += i[r + 3] + o[r]; * return {as: "A1" + n + i.slice(-3), cp: i.slice(0, 3) + l + "E1"} * } * </p> */ public static Map<String, String> getAsCp() { int t = (int) (System.currentTimeMillis() / 1000); String i = Integer.toHexString(t).toUpperCase(); String e = getMD5(t + "").toUpperCase(); String s = e.substring(0, 5); String o = e.substring(e.length() - 5, e.length()); String n = ""; for (int j = 0; 5 > j; j++) { n += s.substring(j, j + 1) + i.substring(j, j + 1); } String l = ""; for (int r = 0; 5 > r; r++) { l += i.substring(r + 3, r + 3 + 1) + o.substring(r, r + 1); } String as = "A1" + n + i.substring(i.length() - 3, i.length()); String cp = i.substring(0, 3) + l + "E1"; Map<String, String> map = new HashMap<>(); map.put(Constant.AS, as); map.put(Constant.CP, cp); return map; } /** * 对字符串 MD5 加密 */ public static String getMD5(String str) { try { // 生成一个 MD5 加密计算摘要 MessageDigest md = MessageDigest.getInstance("MD5"); // 计算 MD5 函数 md.update(str.getBytes()); // digest() 最后确定返回 MD5 hash 值, 返回值为8为字符串 // 因为 MD5 hash 值是16位的hex值, 实际上就是8位的字符 // BigInteger 函数则将8位的字符串转换成 16 位 hex 值, 用字符串来表示得到字符串形式的 hash 值 return new BigInteger(1, md.digest()).toString(16); } catch (Exception e) { ErrorAction.print(e); } return ""; } }
java refer:
package com.meiji.toutiao.api; | |
import com.meiji.toutiao.bean.media.MediaProfileBean; | |
import com.meiji.toutiao.bean.media.MediaWendaBean; | |
import com.meiji.toutiao.bean.media.MultiMediaArticleBean; | |
import io.reactivex.Observable; | |
import okhttp3.ResponseBody; | |
import retrofit2.Call; | |
import retrofit2.http.GET; | |
import retrofit2.http.Query; | |
/** | |
* Created by Meiji on 2017/5/20. | |
*/ | |
public interface IMobileMediaApi { | |
/** | |
* 头条号主页信息 | |
* https://is.snssdk.com/user/profile/homepage/v3/json/?media_id=4377795668&to_html=0&source=article_top_author&refer=all | |
* | |
* @param mediaId 头条号ID | |
*/ | |
@GET("https://is.snssdk.com/user/profile/homepage/v3/json/?to_html=0&source=article_top_author&refer=all&aid=13") | |
Observable<MediaProfileBean> getMediaProfile( | |
@Query("media_id") String mediaId); | |
/** | |
* 获取头条号文章 | |
* https://is.snssdk.com/pgc/ma/?page_type=1&max_behot_time=1495181160&media_id=52445544609&output=json&is_json=1&count=10&from=user_profile_app&version=2&as=479BB4B7254C150&cp=585DB1871ED64E1 | |
* | |
* @param mediaId 头条号ID | |
* @param maxBehotTime 时间轴 | |
*/ | |
@GET("https://is.snssdk.com/pgc/ma/?page_type=1&output=json&is_json=1&count=20&from=user_profile_app&version=2") | |
Observable<MultiMediaArticleBean> getMediaArticle( | |
@Query("media_id") String mediaId, | |
@Query("max_behot_time") String maxBehotTime, | |
@Query("as") String as, | |
@Query("cp") String cp); | |
/** | |
* 获取头条号视频 | |
* https://is.snssdk.com/pgc/ma/?page_type=0&max_behot_time=1495181160&media_id=52445544609&output=json&is_json=1&count=10&from=user_profile_app&version=2&as=479BB4B7254C150&cp=585DB1871ED64E1 | |
* | |
* @param mediaId 头条号ID | |
* @param maxBehotTime 时间轴 | |
*/ | |
@GET("https://is.snssdk.com/pgc/ma/?page_type=0&output=json&is_json=1&count=10&from=user_profile_app&version=2") | |
Observable<MultiMediaArticleBean> getMediaVideo( | |
@Query("media_id") String mediaId, | |
@Query("max_behot_time") String maxBehotTime, | |
@Query("as") String as, | |
@Query("cp") String cp); | |
/** | |
* 获取头条号问答 | |
* https://is.snssdk.com/wenda/profile/wendatab/brow/?other_id=6619635172&format=json&from_channel=media_channel | |
* | |
* @param mediaId 头条号ID | |
*/ | |
@GET("https://is.snssdk.com/wenda/profile/wendatab/brow/?format=json&from_channel=media_channel") | |
Observable<MediaWendaBean> getMediaWenda( | |
@Query("other_id") String mediaId); | |
/** | |
* 获取头条号问答(加载更多) | |
* http://is.snssdk.com/wenda/profile/wendatab/loadmore/?other_id=53294853357&format=json&from_channel=media_channel&cursor=6428177292098273538&count=10&offset=undefined | |
* | |
* @param mediaId 头条号ID | |
* @param cursor 偏移量 | |
*/ | |
@GET("http://is.snssdk.com/wenda/profile/wendatab/loadmore/?format=json&from_channel=media_channel&count=10&offset=undefined") | |
Observable<MediaWendaBean> getMediaWendaLoadMore( | |
@Query("other_id") String mediaId, | |
@Query("cursor") String cursor); | |
/** | |
* 获取头条号动态 | |
* https://is.snssdk.com/dongtai/list/v11/?user_id=6619635172&max_cursor=1494916016999 | |
* | |
* @param mediaId 头条号ID | |
* @param maxCursor 偏移量 | |
*/ | |
@GET("https://is.snssdk.com/dongtai/list/v11/?") | |
Call<ResponseBody> getMediaDongtai( | |
@Query("user_id") String mediaId, | |
@Query("max_cursor") int maxCursor); | |
} |