【React Native实战教程】GitHub Trending API数据的获取

前端之家收集整理的这篇文章主要介绍了【React Native实战教程】GitHub Trending API数据的获取前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

项目开源地址:GitHub PopularGitHubTrending

GitHub Popular中有个treding模块,该模块是GitHub的treding的手机版,在这个模块中你可以使用只有在PC上才能使用的功能。为了开发这个treding模块我们需要获取GitHub的treding的API数据。不过不幸的的是GitHub并没有开放有关trending的API,所以想调GitHub的treding的API已经是不现实的了。

拨开云雾见月明

为了给GitHub Populartreding模块提供可靠的数据支持,我查遍了所有看似可行的方法,但都没能达到要求。本着只要思想不滑坡,方法总比问题多态度,我打开了https://github.com/trending页面源码研究了起来。

在源码中我发现了能够满足GitHub Populartreding模块的所有数据,但存在如下两个问题:

  1. 冗余的数据太多,我们需要从这些冗余的数据中提取treding模块真正需要的数据。
  2. 这些数据都是HTML格式的,而我们需要的是Json格式的数据。

GitHubTrending项目的开发

经过上述的分析,我们的需求与任务也逐渐明确了,我们需要一个能为我们提供可靠的https://github.com/trending数据的模块,暂且叫它GitHubTrending吧。这个模块需要满足如下需求:

  1. 接受一个url参数,如:https://github.com/trending/
  2. 能够根据url参数返回对应的json或object数据。

为了实现这一需求,我们需要对请求url返回的数据进行解析,提取出我们所需要的数据,下面就跟大家分享GitHubTrending的具体实现:

数据模型TrendingRepoModel

我们需要让GitHubTrending返回一个包含TrendingRepoModel.js的集合,TrendingRepoModel.js代码如下:

  1. /** * TrendingRepoModel * 项目地址:https://github.com/crazycodeboy/GitHubTrending * 博客地址:http://www.devio.org * @flow */
  2.  
  3. export default class TrendingRepoModel {
  4. constructor(fullName,url,description,language,Meta,contributors,contributorsUrl) {
  5. this.fullName = fullName;
  6. this.url = url;
  7. this.description = description;
  8. this.language = language;
  9. this.Meta = Meta;
  10. this.contributors = contributors;
  11. this.contributorsUrl = contributorsUrl;
  12. }
  13. }

从上面代码中可以看出,TrendingRepoModel.js包含了https://github.com/trending/的所以数据的模型。

将HTML解析成TrendingRepoModel

我们通过TrendingUtil.js将HTML解析成包含TrendingRepoModel.js的集合。下面是TrendingUtil.js文件代码

  1. /** * TrendingUtil * 工具类:用于将github trending html 转换成 TrendingRepoModel * 项目地址:https://github.com/crazycodeboy/GitHubTrending * 博客地址:http://www.devio.org * @flow */
  2.  
  3. import TrendingRepoModel from './TrendingRepoModel';
  4. import StringUtil from './StringUtil';
  5.  
  6. export default class TrendingUtil {
  7. static htmlToRepo(responseData) {
  8. responseData = responseData.substring(responseData.indexOf('<li class="repo-list-item'),responseData.indexOf('</ol>')).replace(/\n/,'');
  9. var repos = [];
  10. var splitWithH3 = responseData.split('<h3');
  11. splitWithH3.shift();
  12. for (var i = 0; i < splitWithH3.length; i++) {
  13. var repo = new TrendingRepoModel();
  14. var html = splitWithH3[i];
  15.  
  16. this.parseRepoBaseInfo(repo,html);
  17.  
  18. var MetaNoteContent = this.parseContentOfNode(html,'repo-list-Meta');
  19. this.parseRepoMeta(repo,MetaNoteContent);
  20. this.parseRepoContributors(repo,MetaNoteContent);
  21. repos.push(repo);
  22. }
  23. return repos;
  24. }
  25.  
  26. static parseContentOfNode(htmlStr,classFlag) {
  27. var noteEnd = htmlStr.indexOf(' class="' + classFlag);
  28. var noteStart = htmlStr.lastIndexOf('<',noteEnd) + 1;
  29. var note = htmlStr.substring(noteStart,noteEnd);
  30.  
  31. var sliceStart = htmlStr.indexOf(classFlag) + classFlag.length + 2;
  32. var sliceEnd = htmlStr.indexOf('</' + note + '>',sliceStart);
  33. var content = htmlStr.substring(sliceStart,sliceEnd);
  34. return StringUtil.trim(content);
  35. }
  36.  
  37. static parseRepoBaseInfo(repo,htmlBaseInfo) {
  38. var urlIndex = htmlBaseInfo.indexOf('<a href="') + '<a href="'.length;
  39. var url = htmlBaseInfo.slice(urlIndex,htmlBaseInfo.indexOf('">',urlIndex));
  40. repo.url = url;
  41. repo.fullName = url.slice(1,url.length);
  42.  
  43. var description = this.parseContentOfNode(htmlBaseInfo,'repo-list-description');
  44. var index = description.indexOf('</g-emoji>');
  45. if (index !== -1) {
  46. var indexEmoji = description.indexOf('</g-emoji>');
  47. var emoji = description.substring(description.indexOf('>') + 1,indexEmoji)
  48. description = emoji + description.substring(indexEmoji + '</g-emoji>'.length);
  49. }
  50. repo.description = description;
  51. }
  52.  
  53. static parseRepoMeta(repo,htmlMeta) {
  54. var splitWit_n = htmlMeta.split('\n');
  55. if (splitWit_n[0].search('stars') === -1) {
  56. repo.language = splitWit_n[0];
  57. }
  58. for (var i = 0; i < splitWit_n.length; i++) {
  59. if (splitWit_n[i].search('stars') !== -1) {
  60. repo.Meta = StringUtil.trim(splitWit_n[i]);
  61. break;
  62. }
  63. }
  64. }
  65.  
  66. static parseRepoContributors(repo,htmlContributors) {
  67. var splitWitSemicolon = htmlContributors.split('"');
  68. repo.contributorsUrl = splitWitSemicolon[1];
  69. var contributors = [];
  70. for (var i = 0; i < splitWitSemicolon.length; i++) {
  71. var url = splitWitSemicolon[i];
  72. if (url.search('http') !== -1) {
  73. contributors.push(url);
  74. }
  75. }
  76. repo.contributors = contributors;
  77. }
  78. }

上面代码将HTML解析成一个包含TrendingRepoModel.js的集合,为了去除空行,上述代码中用到了StringUtil.js工具类:

  1. /** * 字符串工具类 * 项目地址:https://github.com/crazycodeboy/GitHubTrending * 博客地址:http://www.devio.org * @flow */
  2. export default class StringUtil {
  3. /* * 去掉字符串左右空格、换行 */
  4. static trim( text ){
  5. if (typeof(text) == "string") {
  6. return text.replace(/^\s*|\s*$/g,"");
  7. }
  8. else{
  9. return text;
  10. }
  11. }
  12. }

上述代码用于去除字符串中左右空格与换行。

GitHubTrending封装

经过上述步骤之后,我们的准备工作已经完成了,下面我们就可以通过GitHubTrending来提供数据了:

  1. /**
  2. * 从https://github.com/trending获取数据
  3. * 项目地址:https://github.com/crazycodeboy/GitHubTrending
  4. * 博客地址:http://www.devio.org
  5. * @flow
  6. */
  7. import TrendingUtil from './TrendingUtil';
  8.  
  9. export default class GitHubTrending {
  10. GitHubTrending(){//Singleton pattern
  11. if (typeof GitHubTrending.instance==='object') {
  12. return GitHubTrending.instance;
  13. }
  14. GitHubTrending.instance=this;
  15. }
  16. fetchTrending(url){
  17. return new Promise((resolve,reject)=>{ fetch(url) .then((response)=>response.text()) .catch((error)=>{ reject(error); console.log(error); }).then((responseData)=>{ try { resolve(TrendingUtil.htmlToRepo(responseData)); } catch (e) { reject(e); } }).done(); }); } }

上述代码接受一个url,然后通过fetchAPI获取url返回的HTML数据,最后将HTML解析成包含TrendingRepoModel.js的集合。

如何使用GitHubTrending

为了方面大家使用,我已将GitHubTrending发布到npm,大家可以通过下列步骤来使用GitHubTrending

安装

打开在终端中运行如下命名进行安装:

  1. npm i GitHubTrending --save

使用

  1. new GitHubTrending().fetchTrending(url)
  2. .then((data)=> {
  3. //
  4. }).catch((error)=> {
  5. //
  6. });

更多用例可参考:GitHubPopular:DataRepository.js

总结

从探索使用官方API,到自己动手去实现它,虽然过程比较曲折,但最终还是完成目标。经过反复测试GitHubTrending
现在已经满足了GitHub Popular项目的需求,而且稳定性还是不错的,感兴趣的小伙伴可以下载GitHub Popular
体验一下。

最后

既然来了,留下个喜欢再走吧,鼓励我继续创作(^_^)∠※

如果喜欢我的文章,那就关注我的博客@ devio.org吧,让我们一起做朋友~~

戳这里,加关注哦:

微博:第一时间获取推送
个人博客:干货文章都在这里哦
GitHub:我的开源项目

猜你在找的React相关文章