閱讀130 返回首頁    go 阿裏雲 go 技術社區[雲棲]


C# 網絡編程之通過豆瓣API獲取書籍信息

這篇文章主要是講述如何通過豆瓣API獲取書籍的信息,起初看到這個內容我最初的想法是在"C# 網絡編程之網頁簡單下載實現"中通過HttpWebResponse類下載源碼,再通過正則表達式分析獲取結點標簽得到信息.但後來發現可以通過豆瓣API提供的編程接口實現.
該文章僅是基礎性C#網絡編程文章,嚐試測試了下豆瓣API,並沒什麼高深的內容.但希望對大家有所幫助,僅供學習.
(警告:文章僅供參考,提供一種想法,否則訪問多次-10次被403 forbidden莫怪.建議認證使用豆瓣API)

一.豆瓣API介紹

在開發之前你需要申請創建一個應用,從而獲取一個新的API Key(唯一標識你的Connect站點和API使用者).
正如豆瓣API快速入門(
https://www.douban.com/service/apidoc/guide)中例子:這個示例中展示了使用API獲得ID為1220562的書的信息, 請求的url如下(注意將{yourapikey}替換為你的API Key).
https://api.douban.com/book/subject/1220562?apikey={yourkeyapi}
返回的XML文檔如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<entry xmlns="https://www.w3.org/2005/Atom" xmlns:db="https://www.douban.com/xmlns/" 
xmlns:gd="https://schemas.google.com/g/2005" 
xmlns:openSearch="https://a9.com/-/spec/opensearchrss/1.0/" 
xmlns:opensearch="https://a9.com/-/spec/opensearchrss/1.0/">
	<id>https://api.douban.com/book/subject/1220562</id>
	<title>滿月之夜白鯨現</title>
	<category scheme="https://www.douban.com/2007#kind" term="https://www.douban.com/2007#book"/>
	<author>
		<name>[日] 片山恭一</name>
	</author>
	<link href="https://api.douban.com/book/subject/1220562" rel="self"/>
	<link href="https://book.douban.com/subject/1220562/" rel="alternate"/>
	<link href="https://img3.douban.com/spic/s1747553.jpg" rel="image"/>
	<link href="https://m.douban.com/book/subject/1220562/" rel="mobile"/>
	<summary>那一年,是聽莫紮特、釣鱸魚和家庭破裂的一年。說到家庭破裂,母親怪自己當初沒有找到好男人,父親則認為當時是被狐狸精迷住了眼,失常的是母親,但出問題的是父親……。</summary>
	<db:attribute name="isbn10">7543632608</db:attribute>
	<db:attribute name="isbn13">9787543632608</db:attribute>
	<db:attribute name="title">滿月之夜白鯨現</db:attribute>
	<db:attribute name="pages">180</db:attribute>
	<db:attribute name="translator">豫人</db:attribute>
	<db:attribute name="author">[日] 片山恭一</db:attribute>
	<db:attribute name="price">15.00元</db:attribute>
	<db:attribute name="publisher">青島出版社</db:attribute>
	<db:attribute name="binding">平裝</db:attribute>
	<db:attribute name="pubdate">2005-1</db:attribute>
	<db:tag count="125" name="片山恭一"/>
	<db:tag count="59" name="日本"/>
	<db:tag count="53" name="日本文學"/>
	<db:tag count="36" name="小說"/>
	<db:tag count="31" name="滿月之夜白鯨現"/>
	<db:tag count="14" name="愛情"/>
	<db:tag count="8" name="純愛"/>
	<db:tag count="8" name="外國文學"/>
	<gd:rating average="7.0" max="10" min="0" numRaters="322"/>
</entry>

此時,我需要做的就是通過輸入的URL獲取返回的XML中的數據,通過HttpWebRequest和HttpWebResponse獲取HTTP請求和應答,並解析XML中的信息(較難).後來我才發現如果想試驗下API,豆瓣是允許在不申請API Key情況下進行API調用(每分鍾請求不超過10次).也就是說我在程序中輸入網址如下即可返回XML.
https://api.douban.com/book/subject/1220562

二.C#獲取豆瓣書籍信息

1.添加命名空間

using System.Net;                      //HTTP
using System.IO;                       //文件 流操作
using System.Text.RegularExpressions;  //正則表達式
using System.Xml;                      //Xml文檔

2.添加按鈕點擊事件

//點擊按鈕"獲取信息"
private void button1_Click(object sender, EventArgs e)
{
    richTextBox1.Clear();
    //獲取輸入的URL
    string url = textBox1.Text.ToString();
    //HttpWebRequest對象實例:該類用於獲取和操作HTTP請求 創建WebRequest對象
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    //HttpWebResponse對象實例:該類用於獲取和操作HTTP應答 
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    //構造字節流
    StreamReader reader = new StreamReader(response.GetResponseStream());
    //流從頭讀至尾
    string xmlUrl = reader.ReadToEnd();
    reader.Close();
    response.Close();
    //調用自定義函數獲取XML信息
    GetInfoXML(xmlUrl);
}

3.自定義函數獲取書籍信息

//獲取豆瓣XML內容並顯示
private void GetInfoXML(string xmlUrl)
{
    try
    {
        //實例Xml文檔
        XmlDocument xmlDoc = new XmlDocument();
        //從指定字符串加載xml文檔 
        xmlDoc.LoadXml(xmlUrl);                       
        //實例解析、加入並移除集合的命名空間及範圍管理
        XmlNamespaceManager xmlNM = new XmlNamespaceManager(xmlDoc.NameTable);
        //將給定命名空間添加到集合 
        xmlNM.AddNamespace("db", "https://www.w3.org/2005/Atom");
        //獲取文檔根元素
        XmlElement root = xmlDoc.DocumentElement;
        //選擇匹配Xpath(內容)表達式的結點列表 
        //函數原型:SelectNodes(string xpath,XmlNamespaceManger nsmgr)
        XmlNodeList nodes = root.SelectNodes("/db:entry", xmlNM);

        //獲取子節點信息
        foreach (XmlNode nodeData in nodes)
        {
            foreach (XmlNode childnode in nodeData.ChildNodes)
            {
                string str = childnode.Name;
                switch (str)
                {
                    case "title":
                        string name = "標題名稱:" + childnode.InnerText + "\r\n\r\n";
                        richTextBox1.AppendText(name);
                        break;                    
                    case "author":
                        string author = "作者:" + childnode.InnerText + "\r\n\r\n";
                        richTextBox1.AppendText(author);
                        break;
                    case "db:attribute":
                        { 
                            //獲取<db:attribute name="XXX">的屬性
                            switch (childnode.Attributes[0].Value)
                            {
                                case "pages":
                                    string pages="總頁數:"+childnode.InnerText+"\r\n\r\n";
                                    richTextBox1.AppendText(pages);
                                    break;
                                case "price":
                                    string price="價格:"+childnode.InnerText+"\r\n\r\n";
                                    richTextBox1.AppendText(price);
                                    break;
                                case "publisher":
                                    string publisher="出版社:"+childnode.InnerText+"\r\n\r\n";
                                    richTextBox1.AppendText(publisher);
                                    break;
                                case "pubdate":
                                    string pubdate="出版日期:"+childnode.InnerText+"\r\n\r\n";
                                    richTextBox1.AppendText(pubdate);
                                    break;
                            }
                            break;
                        }
                    case "summary":                             
                        //顯示內容 WordWrap設置為true自動換行(無需調用Split函數或求字符長度)
                        string summary="內容:"+childnode.InnerText+"\r\n\r\n";                                
                        richTextBox1.AppendText(summary);                             
                        break;
                    case "link":
                        //結點屬性是Attributes[0]卻失敗,不能獲取
                        if (childnode.Attributes[1].Value == "image")
                        {
                            //獲取image路徑 <link rel="image" href="https://xxx.jpg"/> 
                            string imagePath = childnode.Attributes[0].Value;
                            //下載圖片
                            string imageName = "local.jpg";
                            System.Net.WebClient client = new System.Net.WebClient();
                            //下載指定URL資源到本地文件夾
                            //函數原型 DownloadFile(string address,string fileName)
                            client.DownloadFile(imagePath,imageName);
                            //從本地文件中加載圖片
                            this.pictureBox1.Image = Image.FromFile(imageName);
                            //圖像原圖大小
                            this.pictureBox1.SizeMode = PictureBoxSizeMode.Zoom;
                            //下載第二張圖片時總是出現"WebClient請求期間發生異常"
                        }
                        break;
                } //switch
            } //foreach
        } //foreach
    }
    catch (Exception msg) //異常處理
    {
        MessageBox.Show(msg.Message);
    }
} //GetInfoXML

4.運行結果如下


源網址中的書籍信息介紹如下圖所示:

三.遇到的問題及總結

由上圖可以發現我輸入的網址沒有包含API key也能獲取,但我在測試時總是使用的.然後同時我也遇到了一些問題:
1.豆瓣API獲取書籍信息接口,需要傳subjectID或isbnID(國際標準書號),但我想實現的是隻知道書名,就能獲取書籍的信息,而不是僅僅傳入一串URL,這些分析都讓程序內容實現,這是接下來需要做的.
2.在使用WebClient和DownloadFile(string address,string fileName)下載圖片時,當獲取第二張圖片總會提示錯誤"WebClient請求期間發生異常",不知道為啥,但不想使用stream或並發獲取圖片,僅想知道這是為啥?
3.這僅僅是一篇基礎性的介紹使用豆瓣API的文章,目前豆瓣針對已經授權用戶(開發API采用OAuth協議進行鑒權)可以實現很多功能,後麵如果有時間可以寫些“查看用戶信息、用戶友鄰信息、增刪改查用戶收藏、查看評論”的文章.

最後希望該文章對大家有所幫助,如果文章中有錯誤或不足之處,還請海涵.同時文章也參考了一些資料,感謝這些作者.
(By:Eastmount 2014-5-2 下午3點 原創:https://blog.csdn.net/eastmount)
參考資料:
1.豆瓣API快速入門
https://www.douban.com/service/apidoc/guide
2.c#使用豆瓣API-sun8134
這裏非常感謝該文章,在解析XML中我使用SelectSingleNodes方法失敗後,參考了他的方法,也推薦大家去閱讀
https://www.cnblogs.com/sun8134/archive/2010/12/15/1906879.html
3.豆瓣客戶端-zh19900207 該文章僅有界麵,但也是我想實現的功能描述
https://blog.csdn.net/zh19900207/article/details/8586000
4.XmlNode.SelectNodes 方法
https://msdn.microsoft.com/zh-cn/library/4bektfx9.aspx

最後更新:2017-04-03 12:56:30

  上一篇:go 經典白話算法之中綴表達式和後綴表達式
  下一篇:go 用KGdb和VMware調試Linux內核,System Call