← 返回文章流

如何将豆瓣观影记录实时同步至博客中

事情的起因是这样的,前几日在看 idealclover 大佬的博客,不经意间看到了他的豆瓣观影记录,他博客中关于豆瓣观影记录是实时同步的,很好奇是如何实现的,经过查看,他是爬取的豆瓣观影界面来实现的,其实关于豆瓣观影记录,网上也有很多的教程,恰巧自己所学的 Go 语言也可以做简单的爬虫实现其效果,于是开始上手造轮子了,PS:了解到非法爬取网站信息是违法的,之前豆瓣 API 接口,关闭访问,在豆瓣上找了好久,终于在我的主页中找到了对于观影记录的官方提供 RSS 订阅,打开订阅,看到有自己所需要的字段,比较好获取,于是就开始了此项目。 分析 首先,需要获取豆瓣提供的 XML 文件,在我的主页右下角就可以看到 RSS 订阅链接: 找到了订阅地址,点击查看 XML 结构,可以看到豆瓣提供的结构还是挺理想的: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 <rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"> <channel> <title>Meng小羽 的收藏</title> <link>https://www.douban.com/people/debuginn/</link> <description> <![CDATA[ Meng小羽 的收藏:想看、在看和看过的书和电影,想听、在听和听过的音乐 ]]> </description> <language>zh-cn</language> <copyright>© 2013, douban.com.</copyright> <pubDate>Sat, 30 May 2020 09:14:08 GMT</pubDate> <item> <title>看过黑衣人:全球追缉</title> <link>http://movie.douban.com/subject/19971676/</link> <description> <![CDATA[ <table><tr> <td width="80px"><a href="https://movie.douban.com/subject/19971676/" title="Men in Black International"> <img src="https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2558701068.webp" alt="Men in Black International"></a></td> <td> <p>推荐: 力荐</p> </td></tr></table> ]]> </description> <dc:creator>Meng小羽</dc:creator> <pubDate>Sat, 30 May 2020 09:14:08 GMT</pubDate> <guid isPermaLink="false">https://www.douban.com/people/debuginn/interests/2402808825</guid> </item> ...... <channel> 其实,我们提取的主要就是 item 标签下对应的电影信息内容: 1 2 3 4 5 6 7 8 9 10 <item> <title>看过黑衣人:全球追缉</title> <link>http://movie.douban.com/subject/19971676/</link> <description> <![CDATA[ <table><tr> <td width="80px"><a href="https://movie.douban.com/subject/19971676/" title="Men in Black International"> <img src="https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2558701068.webp" alt="Men in Black International"></a></td> <td> <p>推荐: 力荐</p> </td></tr></table> ]]> </description> <dc:creator>Meng小羽</dc:creator> <pubDate>Sat, 30 May 2020 09:14:08 GMT</pubDate> <guid isPermaLink="false">https://www.douban.com/people/debuginn/interests/2402808825</guid> </item> 设计 根据豆瓣官方提供的 XML 标签数据,可以利用 Go 语言中 encoding/xml 包来进行对数据的映射,可以设计成如下结构体: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 // 豆瓣 xml 描述结构体 type Attributes struct { XMLName xml.Name `xml:"rss"` Version string `xml:"version,attr"` Channel Channel `xml:"channel"` } // XML 主题结构拆分 type Channel struct { Title string `xml:"title"` Link string `xml:"link"` Description string `xml:"description"` Language string `xml:"language"` Copyright string `xml:"copyright"` Pubdate string `xml:"pubDate"` MovieItem []MovieItem `xml:"item"` } // 豆瓣 电影列表结构体 type MovieItem struct { Title string `xml:"title"` Link string `xml:"link"` Description string `xml:"description"` Pubdate string `xml:"pubDate"` } 可以和 XML 文件对应字段进行匹配,可以从上面的结构体中我们可以看到,最终我们想获取到的数据就是结构体 MovieItem 的数据。 由于是从网上链接获取数据的,在这里首先我们需要将网上豆瓣提供的 XML 文件转换成 []byte 类型的数据: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // 获取 xml 文件数据 func getXMLData(url string) (data []byte, err error) { // 读取 xml 文件 client := &http.Client{} req, _ := http.NewRequest("GET", url, nil) // 自定义Header req.Header.Set("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)") resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() // 关闭文件 // 读取所有文件内容保存至 []byte data, err = ioutil.ReadAll(resp.Body) if err != nil { return nil, err } return } 上面这个函数实现的就是将 XML 文件保存至 Go 语言的数据结构的操作,现在可以将 XML 文件成功读取出来,接下来就是要进行 XML 字段与上面作出的结构体之间的映射,其实映射至结构体的过程是比较简单的,首先声明 Attributes{} 类型的结构体,之后通过 xml.Unmarshal 来实现映射拷贝,就可以得到对应的结构体类型的数据,由于我们想要的数据是结构体数据中的一部分,即 MovieItem,在得到结构体数据后就可以将想要的这一部分的数据选择抽取出来: 1 2 3 4 5 6 7 v := Attributes{} unMarshalErr := xml.Unmarshal(data, &v) if unMarshalErr != nil { fmt.Printf("xml unmarshal failed, err:%v\n", err) } movieItem := v.Channel.MovieItem Map 转换 在这里我们可以得到结构体中嵌套的结构体,在结构体中有一些字段我们是不想要的,需要进行处理,对于 description 这个字段中,官方提供的是一段 HTML 描述串,其中电影的描述文件是我们所需要的,对于 HTML 字符串的拆分,我们可以借助strings.Split 函数来实现截取,使用 \" 符号截取,虽然可以获取到我们想要的数据了,但是由于这个是嵌套的结构体,我们需要做一个匹配的 map 来进行存储处理好的数据,可以看代码中我的设计: 1 2 3 4 5 6 7 8 9 10 11 MoviesMap := make(map[int]interface{}) for i := 0; i < len(movieItem); i++ { movie := make(map[string]string) description := strings.Split(movieItem[i].Description, "\"") movie["Title"] = string([]rune(movieItem[i].Title)[2:]) movie["Link"] = movieItem[i].Link movie["Img"] = description[7] movie["Pubdate"] = movieItem[i].Pubdate MoviesMap[i] = movie } 外层 map 是采用 map[int]interface{} 类型,在 interface{} 中存储这内层 map map[string]string 类型。 针对于 Img 地址的获取,是现根据特定符号拆分,之后获取制定位置的数据获取的。 1 2 3 0 map[Img:https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2558701068.jpg Link:http://movie.douban.com/subject/19971676/ Pubdate:Sat, 30 May 2020 09:14:08 GMT Title:黑衣人:全球追缉] 1 map[Img:https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2263408369.jpg Link:http://movie.douban.com/subject/1294371/ Pubdate:Thu, 28 May 2020 10:06:23 GMT Title:摩登时代] ...... 最后就是将这个 map 做一下序列化处理,这样就可以返回给前台数据了。 1 data, _ = json.Marshal(Mov

来自 Debug客栈作者主页
在原博客阅读全文 (新标签页打开)

以上内容来自博客订阅源,版权归原作者。关注作者后可以在 关注列表 第一时间查看作者文章。

一起聊聊 0

尊重不同观点

还没有评论。欢迎分享第一个想法。

RSS SUBSCRIPTIONS

选择 RSS 订阅

把博客汇的文章添加到你常用的阅读器。

关注文章 RSS 订阅本订阅需要登录后使用