開發自己的博客轉發插件(跨域)


    接着上一篇的《博客備份小工具3》我有提到“其實想了想,轉發博客干嘛非要在本地客戶端轉發,直接在博客園的頁面用js不就可以達到目的么。想是這么想,還沒嘗試。等我寫完了這個博客就去試試。。”。想法很天真,現實很殘忍。本以為,直接ajax異步post請求就可以把當前頁面的內容發布。可是,問題來了。我們瀏覽的頁面域名是cnblogs.com,而我們后台發布的域名是i.cnblogs.com。跨域了,親。問題既然來了,總不能半途而廢吧。程序的世界沒有辦不到,只有想不到。jsonp專門來干這事的。(jsonp資料傳送門)。   為什么不用《博客備份小工具3》,因為它是CS的。要是可以直接在瀏覽頁面有個按鈕一鍵轉發豈不是爽歪歪。貌似Chrome插件可以專門來干這等壞事。(chrome插件介紹傳送門)。好了就這兩個重要的點了。

   下面來說說主要的實現思路,首先通過插件在瀏覽頁面給自己找塊地盤(添加一個div)。然后div中可以輸入用戶名、密碼登錄,取得文章類型。接着就一鍵發布,把當前頁面的內容通過jsonp跨域傳到自己開發的后台發布~是不是很簡單呢?哈哈,其實我覺得挺難的。中間遇到了很多問題。就現在,估計還有很多的bug。

   好了,先看看效果圖。感覺爽嗎?要是當心安全問題,下面我會把所有源碼開放。大伙可以改進。^_^

一、開辟一片空間

插件content_script中配置的content_script.js,在content_script.js中可以直接操作當前瀏覽頁。哈哈,這還了得,這豈不是到哪里都隨心所欲了。好吧,那么我們給自己開辟一片空間來做想要的操作。

    var mydata = "";
    mydata += "&url=" + document.location.href;
    mydata += "&type=mytype";
    mydata += "&tag=mytag";

    var html = " <div id='chrome_test_div' style='display:none;background-color:#0094ff; position: fixed; top: 0px; left: 0px; width: 100%;z-index:11'>\
        <table style='width:100%'>\
            <tr>\
                <td>用戶名:</td>\
                <td><input id='chrome_test_user' type='text' value='' /></td>\
                <td>密碼:</td>\
                <td><input id='chrome_test_pass' type='password' value='' /></td>\
                <td>\
                    <a href='javascript:void(0);' id='chrome_test_a' >\
登錄\
</a>\
</td>\
<td>\
文章:\
</td>\
<td>\
<span id='chrome_content_title'></span>\
</td>\
\
<td>個人分類:</td>\
<td>\
    <select id='pop_sel_type_text'></select>\
</td>\
\
<td>\
    Tag標簽:\
                </td>\
                <td>\
                    <input type='text' value='' list='pop_sel_tag_text' id='id_pop_sel_tag_text'>\
                    <input type='hidden' id='myhidden' />\
                    <!--<datalist id='pop_sel_tag_text'></datalist>-->\
                </td>\
                <td colspan='2'><input type='button' id='chrome_test_button' value='一鍵轉發'  /></td>\
                <td  id='chrome_meg_td'></td>\
            </tr>\
        </table>\
        <script src='https://git.oschina.net/zhaopeiym/Demo/raw/master/resource/cnblogs/cnblog.Chrome.js?v=123'></script>\
    </div>";

    $("body").prepend(html).css("margin-top", "70px");
    $("#chrome_content_title").text($("#cb_post_title_url").text());
    document.body.scrollTop = 30;
    window.onscroll = function () {
        if (true) {
            var top = document.body.scrollTop;
            if (top <= 0) {
                $("#chrome_test_div").slideDown(200);
            }
            else if (top >= 30) {
                $("#chrome_test_div").slideUp(400);
            }
        }
    }

 

直接添加一個div,然后在div中添加一個table。畫上登錄要的用戶名、密碼、文章標題、后台發布的文章類型、tag標簽、、、等。

二、登錄 獲取 你所有的文章分類。

1、用jsonp發送請求

不知道同學們有沒有注意到上面的代碼中有一段

<script src='https://git.oschina.net/zhaopeiym/Demo/raw/master/resource/cnblogs/cnblog.Chrome.js?v=123'></script>
是的,我所以當前操作頁的js都在這個路徑下。

function chrome_test_login() {
    var username = $("#chrome_test_user").val();
    var password = $("#chrome_test_pass").val();
    var Section_url = "&username=" + username + "&password=" + password;
    $.getJSON(getjsonUrl + '/BolghelpWeb/Handler1.ashx?OperationCMD=login' + Section_url + '&callback=?', function (data) {
        test(data);
    });
}

 

登錄的js。ajax的jsonp使用起來還是蠻方便的。

2、后台代碼的登錄和取文章分類

登錄:

 /// <summary>
 /// 登錄
 /// </summary>
 /// <param name="context"></param>
 public void PostLogin(HttpContext context, string username, string password)
 {
     username = context.Request.QueryString["username"];
     password = context.Request.QueryString["password"];

     string loginurl = "http://passport.cnblogs.com/login.aspx?ReturnUrl=http://www.cnblogs.com/";//
     string result = htmlWeb.Load(loginurl).DocumentNode.InnerHtml;
     String __EVENTVALIDATION = new Regex("id=\"__EVENTVALIDATION\" value=\"(.*?)\"").Match(result).Groups[1].Value;
     String __VIEWSTATE = new Regex("id=\"__VIEWSTATE\" value=\"(.*?)\"").Match(result).Groups[1].Value;
     String LBD_VCID_c_login_logincaptcha = new Regex("id=\"LBD_VCID_c_login_logincaptcha\" value=\"(.*?)\"").Match(result).Groups[1].Value;

     StringBuilder str_content = new StringBuilder();
     str_content.Append(@"__EVENTTARGET=");
     str_content.Append(@"&__EVENTARGUMENT=");
     str_content.Append(@"&__VIEWSTATE=" + System.Web.HttpUtility.UrlEncode(__VIEWSTATE, Encoding.UTF8));
     str_content.Append(@"&__VIEWSTATEGENERATOR=C2EE9ABB");
     str_content.Append(@"&__EVENTVALIDATION=" + System.Web.HttpUtility.UrlEncode(__EVENTVALIDATION, Encoding.UTF8));
     str_content.Append(@"&tbUserName=" + System.Web.HttpUtility.UrlEncode(username, Encoding.UTF8));
     str_content.Append(@"&tbPassword=" + password);
     str_content.Append(@"&LBD_VCID_c_login_logincaptcha=" + LBD_VCID_c_login_logincaptcha);
     str_content.Append(@"&LBD_BackWorkaround_c_login_logincaptcha=");
     str_content.Append(@"&btnLogin=登  錄");
     str_content.Append(@"&txtReturnUrl=http://www.cnblogs.com/");

     httphelp.PostHtml(loginurl, null, str_content.ToString(), Encoding.UTF8, true);
 }

 

取文章分類:

/// <summary>
/// 取文章類型
/// </summary>
/// <param name="context"></param>
public void PostGetType(HttpContext context)
{
    PostLogin(context, "", "");

    string TypeUrl = "http://i.cnblogs.com/EditArticles.aspx?opt=1";//地址                                
    var typeHtml = httphelp.PostHtml(TypeUrl, null, "", Encoding.UTF8, true);
    HtmlAgilityPack.HtmlDocument response = new HtmlDocument();
    response.LoadHtml(typeHtml);
    var html_trS = response.DocumentNode.SelectNodes("//*[@id='Editor_Edit_APOptions_Advancedpanel1_cklCategories']/tr");

    List<object> objs = new List<object>();
    foreach (var item in html_trS)
    {
        var html_tdS = item.SelectNodes(item.XPath + "/td");
        foreach (var item_td in html_tdS)
        {
            if (item_td.SelectSingleNode(item_td.XPath + "/input") != null)
            {
                var value = item_td.SelectSingleNode(item_td.XPath + "/input").Attributes["value"].Value;
                var name = item_td.SelectSingleNode(item_td.XPath + "/input").Attributes["name"].Value;
                var text = item_td.SelectSingleNode(item_td.XPath + "/label").InnerText;
                objs.Add(new { value = value, text = text, name = name });
            }
        }
    }
    context.Response.ContentType = "application/json";
    string callback = context.Request.QueryString["callback"];
    context.Response.Write(callback + "(" + objs.ToJson() + ")");
}

 

ok,在此就登錄,並取到了所有的文章類型。

三、一鍵發布

其實在發布之前又登錄的一次。為什么呢?因為發布需要登錄,之前登錄的是上一次請求。而上一次請求的session,在這一個是讀不到的。可能是因為跨域請求的原因。那沒辦法的,那就再登錄一次吧。反正登錄的反法已經獨立出來了。只是電腦多干事了。

1、首頁在前台頁面取得要轉發的正文內容

//一鍵轉發
$("#chrome_test_button").click(function () {
    $("#chrome_meg_td").html("");

    var type = $("#pop_sel_type_text").val().split('%')[0];
    var name = $("#pop_sel_type_text").val().split('%')[1];
    var username = $("#chrome_test_user").val();
    var password = $("#chrome_test_pass").val();
    var tag = $("#id_pop_sel_tag_text").val();
    var Section_url = "&type=" + type + "&tag=" + tag + "&name=" + name + "&password=" + password + "&username=" + username;
    $.getJSON(getjsonUrl + '/BolghelpWeb/Handler1.ashx?OperationCMD=Publishing&callback=?' + Section_url + '&url=' + document.location.href, function (data) {
        $("#chrome_meg_td").html("發布成功~<a href='http://i.cnblogs.com/EditArticles.aspx'  target='_blank'>后台查看~</a>");
        $("#chrome_test_div a").css("color", "#fff");
    });
});

 

2、然后是后台發布

 /// <summary>
 /// 發布
 /// </summary>
 /// <param name="context"></param>
 public void PostPublishing(HttpContext context)
 {
     string url = "http://i.cnblogs.com/EditArticles.aspx?opt=1";//地址   

     string callback = context.Request.QueryString["callback"];
     string mydataurl = context.Request.QueryString["url"];
     string mydatatype = context.Request.QueryString["type"];
     string mydatatag = context.Request.QueryString["tag"];
     string mydataname = context.Request.QueryString["name"];

     PostLogin(context, "", "");
     var html = httphelp.PostHtml(url, null, "", Encoding.UTF8, true);
     String __VIEWSTATE = new Regex("id=\"__VIEWSTATE\" value=\"(.*?)\"").Match(html).Groups[1].Value;
     string title = "test", body = "test";
     GetRequest(mydataurl, ref body, ref title);

     body += "</br>==================================<a  href='" + mydataurl + "' target='_blank'>原文鏈接</a>===此文章由<a href='http://www.cnblogs.com/zhaopei/' target='_blank'>博客轉發插件</a>轉發==================================";

     StringBuilder str_content = new StringBuilder();
     str_content.Append(@"__VIEWSTATE=" + System.Web.HttpUtility.UrlEncode(__VIEWSTATE, Encoding.UTF8));//隨便分類信息和__VIEWSTATE有關    所以 分類  不好弄
     str_content.Append(@"&__VIEWSTATEGENERATOR=FE27D343");//FE27D343   0512620B
     str_content.Append(@"&Editor$Edit$txbTitle=" + System.Web.HttpUtility.UrlEncode("【轉】" + title, Encoding.UTF8));
     str_content.Append(@"&Editor$Edit$EditorBody=" + System.Web.HttpUtility.UrlEncode(body, Encoding.UTF8));
     str_content.Append(@"&" + mydataname + "=" + mydatatype);
     str_content.Append(@"&Editor$Edit$Advanced$ckbPublished=on");//發布
     str_content.Append(@"&Editor$Edit$Advanced$chkDisplayHomePage=on");//博客首頁顯示
     str_content.Append(@"&Editor$Edit$Advanced$chkComments=on");//允許評論
     str_content.Append(@"&Editor$Edit$Advanced$chkMainSyndication=on");//顯示在RSS中
     str_content.Append(@"&Editor$Edit$Advanced$txbEntryName=");//友好地址名,只能使用字母、數字、-連字符、_下划線,不超過150個字符
     str_content.Append(@"&Editor$Edit$Advanced$txbExcerpt=");//插入摘要右側圖片
     str_content.Append(@"&Editor$Edit$Advanced$txbTag=" + mydatatag);// Tag標簽
     str_content.Append(@"&Editor$Edit$Advanced$tbEnryPassword=");//密碼保護
     str_content.Append(@"&Editor$Edit$lkbPost=發布");

     var srcString = httphelp.PostHtml(url, null, str_content.ToString(), Encoding.UTF8, true);//發布

     context.Response.ContentType = "application/json";
     //輸出:回調函數名(json數據)
     if (srcString.Contains("發布成功"))
         context.Response.Write(callback + "('ok')");
     else
         context.Response.Write(callback + "('no')");
 }

 

基本上就此完工了。哈哈~

四、怎么使用

有人可能還不知道怎么安裝插件。360瀏覽器你只有把插件直接拖到瀏覽器里面就可以了。如果是谷歌原版瀏覽器那么就拖到chrome://extensions/這個頁面。還有問題就百度怎么安裝插件吧。

不想看源碼的 可以直接下載插件使用,安裝后打開任何一個博客園文章頁面,然后把滾動條滾到最上就可以看到效果了(效果比較隱藏,為了不影響大家正常瀏覽頁面內容)。 【下載地址】

 

五、源碼下載

全部源碼下載(包括插件源碼、后台源碼和引用的外部js)。親,老規矩。如果覺得對您有用,而您又下載了。請您輕輕的點個贊唄~~

 

 PS:這篇文章本來是寫於2015-04-02 20:25,准備第二天發布。然,第二天發現登錄不了了。原來正好遇上的博客園修改登錄方式。整了老半天也沒有整出怎么登錄,無意看到了一篇文章,借鑒了下思路。搞定!!這里主要也是弄着玩玩,還有很多功能后續再繼續完善。如:記住密碼、自動登錄取分類數據、驗證碼問題(一般只有晚上才需要)、當然肯定還有很多bug,先這樣吧,之后再慢慢修改。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM