Django Model设计:

先设计两张表,一张用来存储专辑(专辑名,封面图,专辑id,添加时间),另外一张存储专辑下每一集的信息(所属的专辑,序号,trackid,音频地址,添加时间)

class XimalayaMediaAlbum(models.Model):"""喜马拉雅专辑"""name = models.CharField(max_length=50, verbose_name="专辑名称")imgurl=models.CharField(max_length=200,verbose_name=u'封面',default='')index=models.IntegerField(verbose_name=u'喜马拉雅专辑id')add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")class Meta:verbose_name = "喜马拉雅音频专辑"verbose_name_plural = verbose_namedef __str__(self):return "{}-{}".format(self.name,self.index)class XimalayaMedia(models.Model):"""喜马拉雅media"""album=models.ForeignKey(XimalayaMediaAlbum,verbose_name=u'专辑',default='')index=models.IntegerField(verbose_name=u'序号')xmlyid=models.IntegerField(verbose_name=u'喜马拉雅id')url = models.CharField(max_length=500, verbose_name="地址")add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")class Meta:verbose_name = "喜马拉雅音频"verbose_name_plural = verbose_namedef __str__(self):return "{}-{}".format(self.album,self.index)def getRecord(self):record=XimalayaMediaPlayRecord.objects.filter(media=self).first()if record:return record.timeelse:return ""

为了防止正在爬的时候,有人再次提交。加一个status表。

class XimalayaAlbumScrapStatus(models.Model):"""喜马拉雅爬虫状态"""album = models.CharField(max_length=50, verbose_name="专辑id")status=models.CharField(verbose_name=u'状态',default='running',max_length=50)add_time = models.DateTimeField(default=datetime.now, verbose_name="添加时间")class Meta:verbose_name = "喜马拉雅爬虫状态"verbose_name_plural = verbose_namedef __str__(self):return "{}-{}".format(self.album,self.status)

前端布局:

首页的布局什么的就简单写了,只需要一个输入框,能输入新的专辑id,再来个列表,展示已经爬过的专辑。

输入框的样式是不是很熟悉呀?没错,直接抄的喜马拉雅主页的,连css名字都不想改。

<style>body {min-height: 100vh;background-image: url("/static/images/intro-2.jpg");background-size: cover;}.mid-content {text-align: center;padding: 50px 0;width: 1200px;height: 300px;margin: 0 auto;}.header {font-family: 'PingFangSC-Medium', 'Microsoft YaHei', sans-serif;text-align: center;color: #ffffff;font-size: 20px;font-weight: 700;}input::-webkit-outer-spin-button,input::-webkit-inner-spin-button {-webkit-appearance: none !important;margin: 0;}.nextPre {color: #262728;font-size: 12px;cursor: pointer;}label {color: #fca429;}.xui-header-searchWrapper {display: inline-block;width: 350px;height: 200px;margin-left: 30px;vertical-align: top;}.xui-header-search, .xui-header-search-input {font-family: -apple-system, BlinkMacSystemFont, PingFangSC-Regular, PingFang SC, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, sans-serif;font-size: 14px;-webkit-font-smoothing: antialiased;-webkit-box-sizing: border-box;box-sizing: border-box;margin: 0;list-style: none;height: 40px;}.xui-header-search {padding: 0;position: relative;top: 50%;-webkit-transform: translateY(-50%);-ms-transform: translateY(-50%);transform: translateY(-50%);}.xui-header-search-input {padding: 10px 70px 10px 20px !important;width: 100%;line-height: 1.5;color: #333;background-color: #fff;border: 1px solid #f86442;border-radius: 54px;outline: none;-webkit-transition: all .2s;-o-transition: all .2s;transition: all .2s;}.xui-header-search, .xui-header-search-input {font-family: -apple-system, BlinkMacSystemFont, PingFangSC-Regular, PingFang SC, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, sans-serif;font-size: 14px;-webkit-font-smoothing: antialiased;-webkit-box-sizing: border-box;box-sizing: border-box;margin: 0;list-style: none;height: 40px;}.xui-header-search-button_position {position: absolute;right: 0;top: 0;}.xui-header-search-button {display: inline-block;background-color: #f86442;background-image: -webkit-gradient(linear, left top, right top, color-stop(1%, #ff9973), color-stop(99%, #ff7251));background-image: -webkit-linear-gradient(left, #ff9973 1%, #ff7251 99%);background-image: -o-linear-gradient(left, #ff9973 1%, #ff7251 99%);background-image: linear-gradient(90deg, #ff9973 1%, #ff7251 99%);width: 60px;height: 100%;color: #fff;font-size: 20px;text-align: center;line-height: 40px;border-radius: 0px 54px 54px 0px;cursor: pointer;}.xuicon {display: inline-block;font-style: normal;vertical-align: baseline;text-align: center;text-transform: none;line-height: 1;text-rendering: optimizeLegibility;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}.list-panel {text-align: center;width: 1200px;min-height: 500px;margin: 0 auto;}</style>
<body>
<div class="mainContent"><div class="mid-content"><div class="e-1350701591 xui-header-searchWrapper"><div class="e-1050963283 xui-header-search focused"><input type="number" class="e-1050963283 xui-header-search-input" placeholder="专辑ID" value=""><span class="e-1050963283 xui-header-search-button xui-header-search-button_position"><i class="e-1050963283 xuicon xuicon-web_ic_search startSearch"style="  padding: 10px 0 0 0; font-size: 17px;">确定</i></span></div></div></div><div class="list-panel">{% for album in allAlbum %}<div style="height: 50px;width: 200px;display: inline-block"><a href="{% url 'main' album.index %}"><div style="width:50px;float: left"><img style="width: 100%;"src="{{ album.imgurl }}"></div><div style="color: white;float: left;font-size: 12px;margin: 15px 0 0 10px;width: 100px;overflow: hidden">{{ album.name }}</div><div style="clear: both;"></div></a></div>{% endfor %}</div>
</div>
</body>

输入了albumId之后,post到服务器,开始抓取index---trackid:

<script>$().ready(function () {function CheckStatus(album) {window.location.reload();}$('.startSearch').click(function () {var album = $('input').val();if (album == "") {alert('请输入');return false;}var fd = new FormData();fd.append('album', album);var xhr = new XMLHttpRequest();xhr.onreadystatechange = function () {if (xhr.readyState == 4 && xhr.status == 200) {var data = eval('(' + xhr.responseText + ')')console.log(data);alert(data.msg);if (data.status == "success") {setInterval(function () {CheckStatus(album);}, 5000);}}};xhr.open('POST', "/listen/");xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");xhr.send(fd);});});
</script>

首页路由url配置:

    url(r'^listen/$', ListenMainPageView.as_view(), name='listen_main'),

View中处理逻辑:

class ListenMainPageView(View):def get(self, request):allAlbum=XimalayaMediaAlbum.objects.all()return render(request, 'mainPage/index.html', locals())def post(self, request):def ScrapByAlbum(album):def startScrap(album):print('Scraping')manager = ScrapManager(album)manager.start()thread = threading.Thread(target=startScrap, args=(album,))thread.start()XimalayaAlbumScrapStatus.objects.get_or_create(album=album)album = request.POST.get('album', None)ret = {}# 查看是否已经在爬取中statusRecord = XimalayaAlbumScrapStatus.objects.filter(album=album).first()if statusRecord:ret['status'] = 'fail'ret['msg'] = '正在爬取中'else:#查看是否已存在专辑if XimalayaMediaAlbum.objects.filter(index=album).count():ret['status'] = 'fail'ret['msg'] = "已存在"else:ret['status'] = 'success'ret['msg'] = "开始爬取"ScrapByAlbum(album)return HttpResponse(json.dumps(ret), content_type="application/json")

把之前的两个接口封装到class ScrapManager中,没啥特别的地方,只是看起来要简洁些:

class ScrapManager:def __init__(self, album=""):self.album_id = albumself.executor = ThreadPoolExecutor(max_workers=10)self.trackTotalCount=Noneself.successCount=0self.allTasks=[]self.headers = {'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8','Accept-Encoding': 'gzip, deflate','Accept-Language': 'zh-CN,zh;q=0.9','Cache-Control': 'max-age=0','Connection': 'keep-alive','Host': 'www.ximalaya.com','If-None-Match': 'W/"2cc08-HvI5ufGZ9TNYyyZOgJLO8mPSV64"','Upgrade-Insecure-Requests': '1','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}def start(self):self.createAlbum()def getAlbumInfor(self):s = requests.session()ret = s.get(url='http://www.ximalaya.com/youshengshu/{}/'.format(self.album_id), headers=self.headers).content.decode('utf-8')soup = BeautifulSoup(ret,"html.parser")title = soup.img['alt']src = soup.img['src']return title, srcdef createAlbum(self):title,src=self.getAlbumInfor()self.album_instance, create = XimalayaMediaAlbum.objects.get_or_create(index=self.album_id,name=title,imgurl=src)self.getIndexAndID()self.checkScrapStatus()def checkScrapStatus(self):XimalayaAlbumScrapStatus.objects.filter(album=self.album_id).delete()def getDownloadUrl(self,id):print('geting src from xmly web for {}'.format(id))s = requests.session()ret = s.get(url='http://www.ximalaya.com/revision/play/tracks?trackIds={}'.format(id), headers=self.headers).contentj = json.loads(ret)src = j['data']['tracksForAudioPlay'][0]['src']if src and src!="" and 'm4a' in src:media= XimalayaMedia.objects.filter(xmlyid=id).first()if media:media.url=srcmedia.save()return srcelse:return ""def getIndexAndID(self):for i in range(1,1000):pageurl = 'http://www.ximalaya.com/revision/album/getTracksList?albumId={}&pageNum={}'.format(self.album_id, i)s = requests.session()ret = s.get(url=pageurl, headers=self.headers).content.decode('utf-8')j = json.loads(ret)if not self.trackTotalCount:self.trackTotalCount=int(j['data']['trackTotalCount'])tracks = j['data']['tracks']if len(tracks) > 0:for track in tracks:# task = self.executor.submit(self.getDownloadUrl, index=track['index'], id=track['trackId'])# self.allTasks.append(task)XimalayaMedia.objects.get_or_create(album=self.album_instance, index=track['index'], xmlyid=track['trackId'])else:break

python django打造自己的喜马拉雅 3(主页前端+数据库)相关推荐

  1. python django打造自己的喜马拉雅 2(分析喜马拉雅接口)

    背景和实现功能,参考上集介绍 分析喜马拉雅接口: 打开浏览器调试窗口,找了半天,也没找到html中的audio标签,看来喜马拉雅没有用html5默认的音频播放器. 终于在network窗口,发现了音频 ...

  2. python django打造自己的喜马拉雅 1(背景和功能介绍)

    背景: 最近在听喜马拉雅有声书"侯卫东官场笔记". 故事很吸引人,阿陈播音也非常到位.只是有一个痛点:每一集开头有长达40秒的片头介绍,声音非常大,而且每一集都重复.晚上躺在床上听 ...

  3. python django mysql结果获取_Django中从mysql数据库中获取数据传到echarts方式

    尝试了几种方法,感觉过于复杂,于是自己写了一个方法. (1)首先在要绘图的页面传入从数据库中提取的参数,这一步通过views可以实现: (2)然后是页面加载完成时执行的函数ready,调用方法f; ( ...

  4. 计算机毕业设计python+django股票基金模拟交易系统(源码+系统+mysql数据库+Lw文档)

    项目介绍 股票信息管理系统,又称为网站股票信息发布系统,是将网页上的某些需要经常变动的信息,类似各类股票信息.最新产品信息发布和业界动态等更新信息集中管理,并通过信息的某些共性进行分类,最后系统化.标 ...

  5. 计算机毕业设计Python+Django的监控管理系统(源码+系统+mysql数据库+Lw文档)

    项目介绍 在网络越来越发达的今天,监控软件也越来越多.监控程序已经成为人们日常网络生活必不可少的程序.老人小孩自己,没有时间陪伴,我们需要监控,厂区操作间,我们可以通过监控查看自己所需要的信息,本论文 ...

  6. python django mysql写入中文乱码_Django 连接mysql数据库中文乱码

    版本:CentOS6.8 python3.6.4 django1.8.2 数据库pymysql 我使用的终端是CentOS终端,CentOS桌面版安装的pycham,windows使用Navicat连 ...

  7. 基于python Django 餐馆点菜管理系统

    问题描述: 随着网络的迅速发展,越来越多的人开始接受甚至时依赖了网络营业的这种交易形式,传统的点菜模式不仅浪费时间,效率低下,而且特别耗费成本与人力,因此不少商家开始使用网上点菜系统.网上点菜系统是一 ...

  8. python Django 餐馆点菜管理系统 毕业设计 完整代码

    问题描述: 随着网络的迅速发展,越来越多的人开始接受甚至时依赖了网络营业的这种交易形式,传统的点菜模式不仅浪费时间,效率低下,而且特别耗费成本与人力,因此不少商家开始使用网上点菜系统.网上点菜系统是一 ...

  9. Python分布式爬虫打造搜索引擎完整版-基于Scrapy、Redis、elasticsearch和django打造一个完整的搜索引擎网站

    Python分布式爬虫打造搜索引擎 基于Scrapy.Redis.elasticsearch和django打造一个完整的搜索引擎网站 https://github.com/mtianyan/Artic ...

最新文章

  1. 无人驾驶的落地,是一场AI与人的博弈
  2. tensorflow model save and restore
  3. 四种方法使Map线程安全
  4. 在控制台读取用户输入密码,你会么?
  5. 房贷利率不断上涨,贷款买房如何才能节省利息?
  6. 开篇词:如何轻松获得 Offer
  7. ConcurrentProgramming:Atomic 原子类
  8. OPPO K3将登陆印度市场 高性价比能否占据一席之地
  9. javax.servlet.http.HttpServlet was not found
  10. 安装计算机主板应注意,组装计算机并仅更换主板时要注意的事项
  11. 手把手教你玩华为eNSP模拟器
  12. (原创)巧用通道作颜色网
  13. 猿创征文|走技术创新路,展时代宏图梦
  14. 人工智能助力三维几何自动化建模
  15. Guarded Suspension 设计模式
  16. 计算机术语root,root是什么意思
  17. 只要60页!金融量化博士总结的Python数据分析入门知识手册
  18. 一、【s3c2440移植linux-3.5】移植准备
  19. json vue 对象转数组_json 将对象转化成数组第二种方式
  20. [git]tig的安装及使用

热门文章

  1. 【备战面试】每日面试题打卡——Java基础篇
  2. 无线蓝牙耳机哪款好?2021年吃鸡游戏耳机推荐
  3. 如何使用 Github 作为自己的免费图床
  4. 深度学习与神经网络有什么区别
  5. 【Vue基础知识总结 6,字节跳动内部学习资料泄露
  6. 周六,照了个人形象照
  7. 几种时间序列的(不)相关性度量
  8. 【数据库】——聚集索引和非聚集索引
  9. 4C沟通法则16项注意事项 让项目沟通更高效
  10. 计算机主机一直响,电脑开机主机一直响怎么办