这些哪个品质更好?更值得入手,第一个三千,第二第三都是一千八,na&#wu 8198 2198;d

NBA,NBA直播,最专业的NBA中文网站_网易体育
0 ? false : true}}">
= navList[myState.ndNavIndex].totalPage}}">:-)已经到最后啦~
季后赛对阵图
西部第一轮
G4 4.24 8:00
G5 4.26 9:30
西部第一轮
G4 4.24 10:30
西部第一轮
西部第一轮
G5 4.25 待定
东部第一轮
东部第一轮
东部第一轮
G5 4.25 待定
东部第一轮
G5 4.25 待定
东西部战绩排名
球员数据统计
&select name="site" class="left"&&option value="网易" selected="selected"&新闻&/option&&option value=""&网页&/option&&/select&&p&12306首秀被骂的狗血喷头后铁道部找来IBM、阿里巴巴等大企业要解决方案,给出的条件是资金管够但是问题得解决。几大企业最后都拒绝了(其中阿里巴巴最后负责了排队系统的建设)。12306开始自己尝试解决问题。他们发现市面上可以买到的成套解决方案都不足以应付春运购票负载,所以只能自己改进已有的数据库(注:其实是改用&a href=&//link.zhihu.com/?target=http%3A//www.vmware.com/cn/products/vfabric-sqlfire/overview.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&VMware SQLFire/GemFire&/a&,这里我之前理解错误)。以前12306用的是小型机,发现性能严重不足,遂改用x86系统+linux平台(原平台为&a href=&//link.zhihu.com/?target=http%3A//en.wikipedia.org/wiki/HP_Superdome& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&HP Superdome&/a&小型机,UNIX系统,&a href=&//link.zhihu.com/?target=http%3A//en.wikipedia.org/wiki/Adaptive_Server_Enterprise& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Sybase ASE&/a&数据库)。最后他们的核心系统用了十几个节点(现在应该是17节点)的多路Xeon E7(具体几路待考),每个节点配1TB内存,数据库全部在内存中运行。2013年春运,12306系统峰值负载11万tps,与2012年淘宝双11活动峰值负载相当,新的系统基本经受住了考验。&/p&&br&&p&&i&补充:以上内容是我在2013年7月得知的信息,彼时没有任何公开来源提到过12306新系统的技术细节。甚至,当时局外人没人知道12306已经在2012年开始做了技术改造。直到数日之前,铁总首次向媒体公开了技术改造的详情:&/i&&a href=&//link.zhihu.com/?target=http%3A//server.chinabyte.com/151/.shtml& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&分布式集群内存数据技术引领12306技术革命&/a&&i&。这篇文章给出的细节,与我之前看到的内容完全一致。由此我可以确信信息来源是此次技术升级的核心人士。&/i&&/p&&p&&i&另外,关于第三方合作对方给出的信息是IBM、Oracle、Sybase全部不能满足要求,主要是这些厂商的方案部署以后,要升级时不能做到不停机灵活扩展。也就是说,IBM没有做到是他们技术不足“搞不定”。阿里巴巴参与了改造,负责了排队系统。此外,虽然后端经受住了压力,前端却如大家所看到的那样还是频频卡死。到底卡死的原因是前端水平太低还是访问压力太大,暂时没有可靠的信息供判断。&/i&&/p&&br&&p&淘宝的问题是其系统架构是分散度较高的,各个订单之间关联度不大;而12306每出一张票都要对全线路做数据更新(因为一条线路存在多个站点),因此系统负载相较淘宝来说集中很多,直接搬淘宝的方案也无法解决问题。淘宝的应用类型决定了阿里巴巴可以通过部署大量的服务器来分散压力,但12306就不行。其实他们的核心系统的硬件成本不过数百万,不是他们不想采购更多服务器,而是买更多的服务器也没什么用途。最后,在经过软件层面的优化之后,12306的瓶颈其实是核心节点的CPU、内存性能。但是这个性能的提升不是朝夕的事情,而是受限于摩尔定律,基本上每两年才能翻一倍多些。(这段话是我自己的分析,不过现在12306的后端数据库系统应付现有需求已经够用了)&/p&&i&补充:关于座位实时复用,我看到的信息明确表明12306出票时,每出一张区间票都要实时调整该线路其他受影响区间段的余票数量,且这是很大的压力来源;另外,对方表示所使用的GemFire数据库与简单的memcache/redis数据缓冲不同,有着本质区别。&/i&&br&&p&==========================&/p&&p&然后我说点对铁路系统购票困难现象的看法:&/p&&br&&p&一种商品只要出现供不应求现象,那么结果只有两种:大家排队购买;出现黑市,变相提高商品的流通价格并抑制需求。&/p&&br&&p&12306这个事情,就是标准的限价商品供不应求之后出现排队与黑市现象的例子。因为供不应求,所以有了黄牛、抢票软件与秒杀。如果供应充足,一个车次直到发车前都有一两张余票,那么黄牛、抢票就毫无存在价值,旅客也用不着守在电脑前和其他人比拼手速和网速以及电脑性能网络性能了。&/p&&br&&p&现在供应不足的前提下,12306就算把系统做的性能再高,也只是会加快热门车次票务秒杀的速度而已——而这更会刺激抢票软件,大家为了在更短的时间里成功抢到队列名额就会不断提升自己的抢票性能。打个比方说就是一个店门前排队,消费者为了增加买到商品的概率去雇人代排,每个消费者都雇了好多人,造成店门口的通道拥挤不堪。为了减缓拥堵,商家不断拓宽通道,但每次一拓宽消费者们就会增加雇佣的排队劳力把新增的通道空间占满,形成恶性循环。这样下去,只要还存在供不应求的现象,这种循环就不会有终止的时候。也就是说,12306的问题主要不是出在网站本身。&/p&&br&&p&那么怎样解决供应不足的问题?这么多年来铁路不断升级运力修建新线,已经建成全球最庞大的铁路运输系统,可是到了春运还是只能勉强应付。从这个角度来说铁路部门在供应不足的问题上也不该承担太大责任,他们已经做得很不错了。&/p&&br&&p&那么问题的根源就出在不断增加的需求上了。为什么我国铁路系统需要承担如此庞大的客运流量需求?很显然,是因为全国范围的人口流动。大量务工上学人员过节要返乡,节后回驻地,这个刚性需求是合理的。可是为什么他们必须要到外地去打工上学?为什么数以亿计的人员要远离家乡去谋生求学?&/p&&br&&p&最后我们会发现,区域发展不平衡才是罪魁祸首。正因为多少人在家乡无法得到足够的机会与资源,他们必须到发达地区奋斗和实现自己的价值。只要这种不平衡现象还在继续,每年春节前后就不可避免地出现大批人员全国范围流动的情况,就不可避免地出现运输能力不足的尴尬。改进12306也好,增加铁路网投资也好,最终都只是治标不治本。如果这个社会不去直面根本问题,那么这些表象的症结永无解开的时候。&/p&&br&&p&说起来,有几个人愿意背井离乡呢?&/p&&p&=============================================&/p&&p&然后这个问题争了几天,我实在忍不住要吐槽一下了:&/p&&br&&p&12306这个事情,网上有多少网友从一开始就献计献策了,也有不少网友提供了很不错的建议。但不得不说,很多网友在提建议时完全就是一种居高临下、自以为是的态度,上来就先认定需求简单可以轻松应付,随便有点经验的工程师就能搞定,12306出问题全怪体制太烂,国企效率低下,一帮人光拿钱不做事,技术水平太低……&/p&&br&&p&淘宝2013年双11活动,峰值流量是一秒钟完成1.3万笔订单。1年1月6日全天网络出票400万张。看起来双11流量完爆12306是吧?等等!别忘了1万张票可不是全天悠悠闲闲平均地卖出去的,而是分成10个时段集中被抢走的。每个时段开始放票后数分钟之内大部分票就已经被抢光了。以每个时段40万票,峰值持续三分钟估算,高峰期一分钟出票在10万张以上毫不夸张。诚然,一分钟10万订单还比不上淘宝2013双11,但别忘了一年以前阿里巴巴也只是达到了一分钟15万订单的水平而已(并且在高峰期一样卡爆)。而且一分钟10万出票还满足不了需求的,以旅客购票的热情来看,达到一分钟50万票都不一定能让所有旅客满意。&/p&&br&&p&淘宝在2012年双11时已经是业界顶尖水平了,其软硬件技术皆为自主研发,既便如此面对一分钟十几万的订单量都会卡死。请问,觉得12306“需求简单,问题可以轻松解决”的,是不是水平已经高到了阿里巴巴都要请你们去领导整个技术团队的级别呢?是不是你们的方案可以轻松应付每分钟数十万笔订单,达到全球一流水平了?&/p&&br&&p&淘宝面临的需求是业界从未有过的,所以淘宝的路很艰难。12306面临的需求是其他人遇到过的么?全世界哪个国家、哪种客运票务系统敢说自己的负载达到12306三分之一的水平?面对空前庞大的压力,诸位“技术高手”只是凭着自己一点程序员的经验,在电脑前一个人思考上一会儿就给出个“简单、实用、省钱、轻松应付”的解决方案——你们知不知道“自大”这两个字怎么写啊?&/p&&br&&p&作为局外人,本来就难以了解铁路售票系统内部的业务逻辑。想出建议可以,那么是不是先收集些信息,了解下背景?是不是先拉出一份需求清单来,把客户的想法搞明白搞清楚了,然后再考虑技术实现?能不能不要上来就想着技术上怎么方便怎么做,把客户需求随意地简化?好多人提的方案在票务供应不足的情况下直接就超售了,难道你要让旅客前一分钟还为订到票高兴,下一分钟对着“您的票被取消”的提示破口大骂么?或者订票延迟确认——知不知道旅客看到选择的车次没能买到票后会做什么?马上去看其他车次有没有票啊!你延迟确认几分钟,然后对排队的账户做抽签,多少旅客会觉得自己被耽误了啊!旅客的要求就是速度越快越好,最好是下订单后一秒钟出结果才安心哩。这还仅仅是简单想一下就能知道的问题,局外人不了解或不能轻易想到的问题又有多少?诸位高谈阔论时,有没有虚心地去找找内部人士了解或者搜索类似的票务系统的研究论文?真觉得自己的头脑聪明绝顶,连背景调查都不做就可以轻松把握所有细节?还有,你们想出来的方案做没做过实验啊?考虑没考虑过硬件适配性啊?你们了解现在市面上能买到的硬件系统,什么样级别的能满足可靠性、性能和可扩展性、可维护性的需求么?你们在多路服务器平台上验证过你们的分布式数据库构想么?哦原来你们什么都没做过,怕是连多节点集群互联该用什么连接方式都不知道,你们拍下脑瓜,一句“那些问题都好解决”就完事儿了?就算你们自己没做过,找找类似的案例会累死么?研究下别人做过的经验就不够高贵冷艳么?就贬低自己技术水平了么?连类似的案例研究都没有,随口就是别人做得到我做得到,真觉得自己写过几行代码就多么伟大了么?&/p&&br&&p&还有一些人,看说IBM没做就一口认定是12306故意排挤IBM,认定IBM解决这问题肯定没压力。好嘛,IBM什么时候做过如此规模的票务系统了?你细节什么都不知就预设结论了?为啥淘宝当年没选择IBM作为方案提供商而是自主研发?IBM的大数据业务主要集中在金融领域,这不代表它在其他领域就样样精通好不好?它能拿出的方案无非是Power7小型机平台,Power7在数据库性能上又比Xeon E7强多点?然后Power7系统卖多少钱了解么?后续维护难度多大了解么?把适合银行金融行业的平台放到12306来真的合适么?说起来,不就是因为“12306”和“IBM”这俩名字放一起,诸位内心里首先就给前者打了负分对后者仰视么?要是把“12306”换成“nasdaq”,那结论就又是一回事儿了——哦正好nasdaq没用IBM方案,可见nasdaq是排挤IBM内部人赚黑心钱是吧?不过2013年工商银行系统升级故障,应该是和方案提供商IBM无关的,肯定是国企的体制问题无误!&/p&&br&&p&评价一个事物,首先不是了解背景、研究问题产生的原因,首先是看被评价者处于什么立场,打着什么标签。如果是“敌对阵营”那就毫不犹豫地踩上一脚再说话,接下来就算研究也只研究“它的错误在哪儿”,不考虑“它也有对的可能性”。在12306这个问题上就是:12306是国企,是铁总下属机构,所以它出了问题一定是自身原因。票务系统做不好一定是铁路方面不懂技术,把该用来请大企业做方案的钱自己贪掉了,一定不可能是大企业都没信心解决这问题。旅客普遍使用抢票软件也是12306的责任,不是供应不足的原因……&/p&&br&&p&最后呢?12306还是做到了全球最强的客运票务系统。一贯被认为是因循守旧的国企,在选择技术方案时放弃沿用多年的小型机/UNIX平台去拥抱业界还是新鲜事物的基于x86/linux的大规模分布内存数据库系统,承受住了堪比2012年淘宝双11的压力。在这个领域,12306可以自豪地说自己是做的最好的案例。它还在卡,还是偶尔崩溃,页面还是难看,可是这些迟早会改进。这个过程中也还是会有冷嘲热讽,还是会有所谓的大牛指点江山,但最终解决春运高峰期一天数百万张秒杀售票的,还是12306自己。&/p&&br&&p&所以,走自己的路,让别人去说吧。&/p&&p&=======================================================&/p&&p&下面我说说12306系统改进面临的一些问题,一些网友提出的解决方案的可行性。&/p&&br&&p&1.“超级计算机能不能用于12306?”——不能,详情见这个&a href=&http://www.zhihu.com/question//answer/& class=&internal&&页面&/a&;&/p&&br&&p&2.“能不能用一个服务器甚至一个集群处理一个车次来加快速度?”——没有意义,处理速度在硬件上主要受限于每个CPU线程获得的内存带宽与延迟,其中内存延迟更重要一些。一个核心处理还是一台服务器处理,内存延迟这个参数是没什么区别的;&/p&&br&&p&3.“能不能在多地建立集群,分别处理某地的车次?”——道理同上;&/p&&br&&p&4.“能不能取消座位实时复用,降低处理压力?”——如果所有区间站的票数都是预先确定的,那么到最后必然会出现有的冷门区间座位空置的情况,这是旅客不希望看到的;&/p&&br&&p&5.“能不能把座位实时复用改为延时复用,热门车次第一次放票后,根据区间之间的情况在下一个放票点调整各区间票额?”——这样做可以减轻计算压力,但是会让大量旅客在第一次订票失败后等待下一次放票,增加下一次放票的负载。而且这会干扰旅客的抢票计划,原来是一个车次没票后就去找下一个车次,现在是一个车次要抢两次甚至更多,反而让旅客更累;&/p&&br&&p&6.“能不能改成预先排队抽签,放票前订票旅客在网上选择进入队列,放票后抽签决定,避免争抢”——很多人提出类似这样的主意。注意热门车次放票被抢光后,没买到票的旅客会立刻去找其他车次是否有票。也就是说即便有这个预排队功能,也不能阻止没去排队的旅客在放票开始之后去买票。对于热门车次而言,参与预排队的旅客抽签失败的概率非常高,而他们抽签失败后多数会失去对这个功能的信任,转而继续选择抢票的方式,于是很快大多数人都会放弃抽签。如果设定为只有参与预排队的旅客才能买到票,那么抽签失败的旅客就失去了对其他车次的选择权,结果更是一场灾难。希望提出类似方案的网友好好思考我上面这些内容。&/p&&br&&p&7.“12306的负载不是比淘宝小很多么?”——淘宝2013年双11峰值订单数量一分钟79万笔,12306每次放票按500热门车次算,根据&a href=&//link.zhihu.com/?target=http%3A//wx.sina.com.cn/news/m//.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&央视直播春运火车票抢票&/a& 这篇报道,热门车次峰值抢票速度在每分钟500票左右。很容易算出现在12306的峰值订单量在一分钟10万-30万的级别,与淘宝双11峰值是相同数量级。&/p&&br&&p&我在前面提过供求关系是12306面临的核心问题,可能很多没有经济学基础的网友不太明白,我这里再详细解释下。&/p&&br&&p&任何限价商品出现供不应求情况时,最终获得商品的大多数消费者支付的成本都是要超出商品本身的标价的。一个简单的例子,超市限量出售半价鸡蛋,大批顾客去抢购,虽然排队买到的顾客为鸡蛋本身花的钱少了,但是这些顾客付出了在那里排队的时间和人力成本。排了很久队才买到鸡蛋的顾客,为鸡蛋支付的时间与人力成本甚至可能超过了他买半价鸡蛋省下的金额。于此同时,限量供应的条件下必然有一些排队者最终没能买到鸡蛋。之所以有人买到鸡蛋有人没买到,大多数情况下是因为前者比后者付出了更多的成本;排队者是在跟其他排队者竞争,那些看到长长的队伍就放弃的潜在消费者就是竞争的失败者。&/p&&br&&p&12306的情况也是如此。在现有的车票限价限量供应体系下,在某些高峰期有乘车需求的旅客数量大大超过了铁路系统在这些时间段的运输能力。在这个前提下,必然会有大量旅客无法在这些时间段买到车票,被迫改变出行计划或者出行方式;而买到票的旅客为车票支付的成本,大多数情况下都是高于甚至远高于车票本身的标价的。超出的这一部分成本,可以体现为向黄牛买票支付的溢价,可以体现为在车站售票口排队付出的时间精力,而到了12306的时代,就可以体现为为了抢到票而付出的等待成本。&/p&&br&&p&因此,12306无论怎么改进,都不可能降低因为供求关系而产生的旅客获得车票的额外成本。12306改进的结果只是会改变这种额外成本的形式。以前没有网络订票,大家去售票厅排队或者一次又一次打电话;现在有了网络订票,大家在网上卡到骂娘。但大家吐槽12306的种种缺陷时,其实原因并不是旅客真的特别重视网站的美观程度、重视网页的代码是不是高水平,而是还有很多人没能按自己的心意买到车票。旅客对12306的需求只有一条——买到旅客需要的车票;可是12306无法解决这个需求。对于旅客来说,卡三个小时但买到了票的体验是60分,三次放票时每次都一秒钟就被告知票已售完的体验是0分。&/p&&br&&p&于是12306的未来就会很麻烦。随着系统的改进升级,整套系统的负载能力会越来越强大。可是性能的提升意味着热门车次放票后售空的速度越来越快。上面引据的例子里,一个车次一分钟就卖掉500张票;性能改进后,最终达到的效果可能是5秒钟就卖掉全部票额。而对于旅客来说,卖票速度提升并不会减少他们为了获得车票而付出的额外成本——以前是买一张票卡10分钟半小时,现在一个订单几秒钟就确认了,但是为了能在几秒钟里抢过其他旅客,你需要提升你的电脑性能,增加你的网络带宽,降低你的网络延迟;你需要更强大的抢票软件,一秒钟内发起更多的请求……最后,你在硬件设备上增加的投入就是你付出的额外成本,相比之前你在等待网页响应时付出的时间成本来说只是换了形式。以前售票厅时代大家比拼谁去排队排的早,以后大家比拼谁的网络性能好。而且,12306的响应速度越快,旅客之间的设备军备竞赛也就会越激烈。最后,大家会为了降低几十毫秒的延迟购买国内的vpn通道,改用表现更好的网卡,跑到号称能提供更高抢票性能的网吧去抢票……然后还是会有大量用户因为竞争不过其他旅客而被迫改变出行计划或出行方式。而且当旅客纷纷提升自己设备的性能时,对12306的压力也会越来越大,12306自己也必须同步增加性能,投入越来越高的成本。从技术的角度讲,12306面对的是一个随着它自身性能增长而同步甚至更快提升的需求,具有这样残酷要求的类似案例就只有股票、期货电子交易市场而已。甚至,12306最终的压力可能会超过这些市场。&/p&&br&&p&回到最开始的问题:12306包给知名大企业是否会更好?答案是,无论谁来做,最终结果都是一样。&/p&
12306首秀被骂的狗血喷头后铁道部找来IBM、阿里巴巴等大企业要解决方案,给出的条件是资金管够但是问题得解决。几大企业最后都拒绝了(其中阿里巴巴最后负责了排队系统的建设)。12306开始自己尝试解决问题。他们发现市面上可以买到的成套解决方案都不足以…
&figure&&img src=&https://pic3.zhimg.com/v2-c889ea63a0067deccc6a4_b.jpg& data-rawwidth=&640& data-rawheight=&313& class=&origin_image zh-lightbox-thumb& width=&640& data-original=&https://pic3.zhimg.com/v2-c889ea63a0067deccc6a4_r.jpg&&&/figure&&h2&由&a href=&http://link.zhihu.com/?target=https%3A//www.tianmaying.com/user/cliff& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Cliff&/a&发表在&a href=&http://link.zhihu.com/?target=https%3A//www.tianmaying.com/tutorial/music-163-crawler& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&天码营&/a&&/h2&&br&&h2&起因&/h2&&p&前两天在知乎上看到一个帖子《&a href=&https://www.zhihu.com/question/& class=&internal&&网易云音乐有哪些评论过万的歌曲?&/a&》,一时技痒,用Java实现了一个简单的爬虫,这里简单记录一下。&/p&&p&最终的结果开放出来了,大家可以随意访问,请戳这里&&&&&& &a href=&http://link.zhihu.com/?target=http%3A//grri94kmi4.app.tianmaying.com/songs& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&网易云音乐爬虫结果&/a&。&/p&&h2&爬虫简介&/h2&&p&网络爬虫是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本,一个通用的网络爬虫大致包含以下几个步骤:&/p&&figure&&img src=&https://pic4.zhimg.com/v2-400bc7c055ed8a5d0d6aa84c582873ab_b.png& data-rawwidth=&793& data-rawheight=&448& class=&origin_image zh-lightbox-thumb& width=&793& data-original=&https://pic4.zhimg.com/v2-400bc7c055ed8a5d0d6aa84c582873ab_r.jpg&&&/figure&&p&网络爬虫的大致流程如上图所示,无论你是做什么样的爬虫应用,整体流程都是大同小异。现在,我们就根据网易云音乐来定制一个专门爬取音乐评论数量的特定网络爬虫。&/p&&h2&前期准备&/h2&&h3&网页类型分析&/h3&&p&首先,我们需要对&a href=&http://link.zhihu.com/?target=http%3A//music.163.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&网易云音乐&/a&整个网站有个大致的了解,进入&a href=&http://link.zhihu.com/?target=http%3A//music.163.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&网易云音乐首页&/a&,浏览后发现其大概有这么几种类型的URL:&/p&&ul&&li&推荐页面&/li&&li&排行榜列表以及排行榜页面&/li&&li&歌单列表以及歌单页面&/li&&li&主播电台列表以及主播电台页面&/li&&li&歌手列表以及歌手页面&/li&&li&专辑列表(新碟上架)以及专辑页面&/li&&li&歌曲页面&/li&&/ul&&p&我们最终需要爬取的数据在歌曲页面中,该页面里包含了歌曲的名称以及歌曲的评论数量。&/p&&p&另外,我们还需要尽可能多的获取歌曲页面,这些信息我们可以从前面6种类型的页面拿到。其中,歌单列表以及歌单页面结构最简单,歌单列表直接分页就可以拿到。因此,我们选择歌单页面作为我们的初始页面,然后歌单列表--歌单--歌曲一路爬下去即可。&/p&&h3&设计数据模型&/h3&&p&通过上述分析,我们可以知道我们要做两件事情,一是爬取页面歌单列表--歌单--歌曲,二是将最终的结果存储起来。因此,我们只需要两个对象,一个用来存储页面相关的信息,url、页面类型、是否被爬过(html和title作为临时数据存储),另外一个用来存储歌曲相关信息,url、歌曲名,评论数。因此,model类如下:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&public&/span& &span class=&kd&&class&/span& &span class=&nc&&WebPage&/span& &span class=&o&&{&/span&
&span class=&kd&&public&/span& &span class=&kd&&enum&/span& &span class=&n&&PageType&/span& &span class=&o&&{&/span&
&span class=&n&&song&/span&&span class=&o&&,&/span& &span class=&n&&playlist&/span&&span class=&o&&,&/span& &span class=&n&&playlists&/span&&span class=&o&&;&/span&
&span class=&o&&}&/span&
&span class=&kd&&public&/span& &span class=&kd&&enum&/span& &span class=&n&&Status&/span& &span class=&o&&{&/span&
&span class=&n&&crawled&/span&&span class=&o&&,&/span& &span class=&n&&uncrawl&/span&&span class=&o&&;&/span&
&span class=&o&&}&/span&
&span class=&kd&&private&/span& &span class=&n&&String&/span& &span class=&n&&url&/span&&span class=&o&&;&/span&
&span class=&kd&&private&/span& &span class=&n&&String&/span& &span class=&n&&title&/span&&span class=&o&&;&/span&
&span class=&kd&&private&/span& &span class=&n&&PageType&/span& &span class=&n&&type&/span&&span class=&o&&;&/span&
&span class=&kd&&private&/span& &span class=&n&&Status&/span& &span class=&n&&status&/span&&span class=&o&&;&/span&
&span class=&kd&&private&/span& &span class=&n&&String&/span& &span class=&n&&html&/span&&span class=&o&&;&/span&
&span class=&o&&...&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&public&/span& &span class=&kd&&class&/span& &span class=&nc&&Song&/span& &span class=&o&&{&/span&
&span class=&kd&&private&/span& &span class=&n&&String&/span& &span class=&n&&url&/span&&span class=&o&&;&/span&
&span class=&kd&&private&/span& &span class=&n&&String&/span& &span class=&n&&title&/span&&span class=&o&&;&/span&
&span class=&kd&&private&/span& &span class=&n&&Long&/span& &span class=&n&&commentCount&/span&&span class=&o&&;&/span&
&span class=&o&&...&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&h2&获取网页内容并解析&/h2&&p&根据之前的分析,我们需要爬的页面有三种:歌单列表、歌单以及歌曲。为了验证想法的可行性,我们先用代码来解析这三种类型的网页,我们将网页内容获取以及解析的代码都放入CrawlerThread当中。&/p&&h3&获取html&/h3&&p&无论想要从什么网站中拿到数据,获取其html代码都是最最基础的一步,这里我们使用jsoup来获取页面信息,在CrawlerThread中添加如下代码:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&private&/span& &span class=&kt&&boolean&/span& &span class=&nf&&fetchHtml&/span&&span class=&o&&(&/span&&span class=&n&&WebPage&/span& &span class=&n&&webPage&/span&&span class=&o&&)&/span& &span class=&kd&&throws&/span& &span class=&n&&IOException&/span& &span class=&o&&{&/span&
&span class=&n&&Connection&/span&&span class=&o&&.&/span&&span class=&na&&Response&/span& &span class=&n&&response&/span& &span class=&o&&=&/span& &span class=&n&&Jsoup&/span&&span class=&o&&.&/span&&span class=&na&&connect&/span&&span class=&o&&(&/span&&span class=&n&&webPage&/span&&span class=&o&&.&/span&&span class=&na&&getUrl&/span&&span class=&o&&()).&/span&&span class=&na&&timeout&/span&&span class=&o&&(&/span&&span class=&mi&&3000&/span&&span class=&o&&).&/span&&span class=&na&&execute&/span&&span class=&o&&();&/span&
&span class=&n&&webPage&/span&&span class=&o&&.&/span&&span class=&na&&setHtml&/span&&span class=&o&&(&/span&&span class=&n&&response&/span&&span class=&o&&.&/span&&span class=&na&&body&/span&&span class=&o&&());&/span&
&span class=&k&&return&/span& &span class=&n&&response&/span&&span class=&o&&.&/span&&span class=&na&&statusCode&/span&&span class=&o&&()&/span& &span class=&o&&/&/span& &span class=&mi&&100&/span& &span class=&o&&==&/span& &span class=&mi&&2&/span& &span class=&o&&?&/span& &span class=&kc&&true&/span& &span class=&o&&:&/span& &span class=&kc&&false&/span&&span class=&o&&;&/span&
&span class=&o&&}&/span&
&span class=&kd&&public&/span& &span class=&kd&&static&/span& &span class=&kt&&void&/span& &span class=&nf&&main&/span&&span class=&o&&(&/span&&span class=&n&&String&/span&&span class=&o&&[]&/span& &span class=&n&&args&/span&&span class=&o&&)&/span& &span class=&kd&&throws&/span& &span class=&n&&Exception&/span& &span class=&o&&{&/span&
&span class=&n&&WebPage&/span& &span class=&n&&playlists&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&WebPage&/span&&span class=&o&&(&/span&&span class=&s&&&http://music.163.com/#/discover/playlist/?order=hot&cat=%E5%85%A8%E9%83%A8&limit=35&offset=0&&/span&&span class=&o&&,&/span& &span class=&n&&PageType&/span&&span class=&o&&.&/span&&span class=&na&&playlists&/span&&span class=&o&&);&/span&
&span class=&n&&CrawlerThread&/span& &span class=&n&&crawlerThread&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&CrawlerThread&/span&&span class=&o&&();&/span&
&span class=&n&&crawlerThread&/span&&span class=&o&&.&/span&&span class=&na&&fetchHtml&/span&&span class=&o&&(&/span&&span class=&n&&playlists&/span&&span class=&o&&);&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&playlists&/span&&span class=&o&&.&/span&&span class=&na&&getHtml&/span&&span class=&o&&());&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&运行后即可看到html文本的输出&/p&&h3&解析歌单列表页面&/h3&&p&得到html后,我们来解析歌单列表,拿到页面中的所有歌单,Jsoup包含了html解析相关的功能,我们无需添加其他依赖,直接在CrawlerThread中添加如下代码:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&private List&WebPage& parsePlaylist(WebPage webPage) {
Elements songs = Jsoup.parse(webPage.getHtml()).select(&ul.f-hide li a&);
return songs.stream().map(e -& new WebPage(BASE_URL + e.attr(&href&), PageType.song, e.html())).collect(Collectors.toList());
public static void main(String[] args) throws Exception {
WebPage playlists = new WebPage(&http://music.163.com/discover/playlist/?order=hot&cat=%E5%85%A8%E9%83%A8&limit=35&offset=0&, PageType.playlists);
CrawlerThread crawlerThread = new CrawlerThread();
crawlerThread.fetchHtml(playlists);
System.out.println(crawlerThread.parsePlaylists(playlists));
&/code&&/pre&&/div&&h3&解析歌单页面&/h3&&p&和歌单列表页面类似,只需要将歌曲相关的元素找出来即可:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&private List&WebPage& parsePlaylist(WebPage webPage) {
Elements songs = Jsoup.parse(webPage.getHtml()).select(&ul.f-hide li a&);
return songs.stream().map(e -& new WebPage(BASE_URL + e.attr(&href&), PageType.song, e.html())).collect(Collectors.toList());
public static void main(String[] args) throws Exception {
WebPage playlist = new WebPage(&http://music.163.com/playlist?id=&, PageType.playlist);
CrawlerThread crawlerThread = new CrawlerThread();
crawlerThread.fetchHtml(playlist);
System.out.println(crawlerThread.parsePlaylist(playlist));
&/code&&/pre&&/div&&p&注意,这里为了方便,我们将歌曲的名称也拿到了,这样后面我们就不需要再次获取歌曲名称了。&/p&&h3&解析歌曲页面&/h3&&p&终于到歌曲页面了,这里网易云音乐做了反爬处理,获取数据时的参数需要经过加密处理,这里我们不纠结于具体算法,如果有兴趣的直接看参考代码,我们只看关键代码:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&private&/span& &span class=&n&&Song&/span& &span class=&nf&&parseSong&/span&&span class=&o&&(&/span&&span class=&n&&WebPage&/span& &span class=&n&&webPage&/span&&span class=&o&&)&/span& &span class=&kd&&throws&/span& &span class=&n&&Exception&/span& &span class=&o&&{&/span&
&span class=&k&&return&/span& &span class=&k&&new&/span& &span class=&n&&Song&/span&&span class=&o&&(&/span&&span class=&n&&webPage&/span&&span class=&o&&.&/span&&span class=&na&&getUrl&/span&&span class=&o&&(),&/span& &span class=&n&&webPage&/span&&span class=&o&&.&/span&&span class=&na&&getTitle&/span&&span class=&o&&(),&/span& &span class=&n&&getCommentCount&/span&&span class=&o&&(&/span&&span class=&n&&webPage&/span&&span class=&o&&.&/span&&span class=&na&&getUrl&/span&&span class=&o&&().&/span&&span class=&na&&split&/span&&span class=&o&&(&/span&&span class=&s&&&=&&/span&&span class=&o&&)[&/span&&span class=&mi&&1&/span&&span class=&o&&]));&/span&
&span class=&o&&}&/span&
&span class=&kd&&public&/span& &span class=&kd&&static&/span& &span class=&kt&&void&/span& &span class=&nf&&main&/span&&span class=&o&&(&/span&&span class=&n&&String&/span&&span class=&o&&[]&/span& &span class=&n&&args&/span&&span class=&o&&)&/span& &span class=&kd&&throws&/span& &span class=&n&&Exception&/span& &span class=&o&&{&/span&
&span class=&n&&WebPage&/span& &span class=&n&&song&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&WebPage&/span&&span class=&o&&(&/span&&span class=&s&&&http://music.163.com/song?id=&&/span&&span class=&o&&,&/span& &span class=&n&&PageType&/span&&span class=&o&&.&/span&&span class=&na&&song&/span&&span class=&o&&,&/span& &span class=&s&&&test&&/span&&span class=&o&&);&/span&
&span class=&n&&CrawlerThread&/span& &span class=&n&&crawlerThread&/span& &span class=&o&&=&/span& &span class=&k&&new&/span& &span class=&n&&CrawlerThread&/span&&span class=&o&&();&/span&
&span class=&n&&crawlerThread&/span&&span class=&o&&.&/span&&span class=&na&&fetchHtml&/span&&span class=&o&&(&/span&&span class=&n&&song&/span&&span class=&o&&);&/span&
&span class=&n&&System&/span&&span class=&o&&.&/span&&span class=&na&&out&/span&&span class=&o&&.&/span&&span class=&na&&println&/span&&span class=&o&&(&/span&&span class=&n&&crawlerThread&/span&&span class=&o&&.&/span&&span class=&na&&parseSong&/span&&span class=&o&&(&/span&&span class=&n&&song&/span&&span class=&o&&));&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&好吧,获取过程确实比较曲折,经过了多次的加密,不过不管怎么样,最终我们还是拿到了我们想要的数据。接下来,就是使用爬虫将整套机制run起来了。&/p&&h2&实现爬虫&/h2&&p&重新回顾一下流程图,我们发现其中有很重要的一个对象是爬虫队列,爬虫队列的实现方法有很多种,自己实现,mysql、redis、MongoDB等等都可以满足我们的需求,不同的选择会导致我们实现的不一致。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-400bc7c055ed8a5d0d6aa84c582873ab_b.png& data-rawwidth=&793& data-rawheight=&448& class=&origin_image zh-lightbox-thumb& width=&793& data-original=&https://pic4.zhimg.com/v2-400bc7c055ed8a5d0d6aa84c582873ab_r.jpg&&&/figure&&p&综合考虑,我们使用Mysql+ Spring Data JPA + Spring MVC来跑我们的整套框架,最终还可以将爬下来的数据通过web服务展现出来。更深入地学习Spring MVC,请大家参考&a href=&http://link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring MVC实战入门训练&/a&。&/p&&br&&p&确定好之后,我们就可以开始一步步实现了。这里Spring Data JPA的代码就不展示了。了解Spring Data JPA,请参考&a href=&http://link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-data-jpa& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring Data JPA实战入门训练&/a&。直接上核心代码,所有和爬虫整体流程相关的代码我们都放进CrawlerService中。&/p&&h3&初始网址&/h3&&p&第一步建立一个初始网址,我们可以根据歌单列表分页的特征得到:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&private void init(String catalog) {
List&WebPage& webPages = Lists.newArrayList();
for(int i = 0; i & 43; i++) {
webPages.add(new WebPage(&http://music.163.com/discover/playlist/?order=hot&cat=& + catalog + &&limit=35&offset=& + (i * 35), PageType.playlists));
webPageRepository.save(webPages);
public void init() {
webPageRepository.deleteAll();
init(&全部&);
init(&华语&);
init(&欧美&);
init(&日语&);
init(&韩语&);
init(&粤语&);
init(&小语种&);
init(&流行&);
init(&摇滚&);
init(&民谣&);
init(&电子&);
init(&舞曲&);
init(&说唱&);
init(&轻音乐&);
init(&爵士&);
init(&乡村&);
init(&R&B/Soul&);
init(&古典&);
init(&民族&);
init(&英伦&);
init(&金属&);
init(&朋克&);
init(&蓝调&);
init(&雷鬼&);
init(&世界音乐&);
init(&拉丁&);
init(&另类/独立&);
init(&New Age&);
init(&古风&);
init(&后摇&);
init(&Bossa Nova&);
init(&清晨&);
init(&夜晚&);
init(&学习&);
init(&工作&);
init(&午休&);
init(&下午茶&);
init(&地铁&);
init(&驾车&);
init(&运动&);
init(&旅行&);
init(&散步&);
init(&酒吧&);
init(&怀旧&);
init(&清新&);
init(&浪漫&);
init(&性感&);
init(&伤感&);
init(&治愈&);
init(&放松&);
init(&孤独&);
init(&感动&);
init(&兴奋&);
init(&快乐&);
init(&安静&);
init(&思念&);
init(&影视原声&);
init(&ACG&);
init(&校园&);
init(&游戏&);
init(&70后&);
init(&80后&);
init(&90后&);
init(&网络歌曲&);
init(&KTV&);
init(&经典&);
init(&翻唱&);
init(&吉他&);
init(&钢琴&);
init(&器乐&);
init(&儿童&);
init(&榜单&);
init(&00后&);
&/code&&/pre&&/div&&p&这里,我们初始化了歌单所有分类的列表,通过这些列表,我们就能拿到网易云音乐大部分的歌曲。&/p&&h3&从爬虫队列中拿到一个URL&/h3&&p&这里的逻辑非常简单,从mysql中获取一个状态为未爬的网页即可,但是由于我们需要爬的网址非常的多,肯定要用到多线程,因此需要考虑异步的情况:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&public&/span& &span class=&kd&&synchronized&/span& &span class=&n&&WebPage&/span& &span class=&nf&&getUnCrawlPage&/span&&span class=&o&&()&/span& &span class=&o&&{&/span&
&span class=&n&&WebPage&/span& &span class=&n&&webPage&/span& &span class=&o&&=&/span& &span class=&n&&webPageRepository&/span&&span class=&o&&.&/span&&span class=&na&&findTopByStatus&/span&&span class=&o&&(&/span&&span class=&n&&Status&/span&&span class=&o&&.&/span&&span class=&na&&uncrawl&/span&&span class=&o&&);&/span&
&span class=&n&&webPage&/span&&span class=&o&&.&/span&&span class=&na&&setStatus&/span&&span class=&o&&(&/span&&span class=&n&&Status&/span&&span class=&o&&.&/span&&span class=&na&&crawled&/span&&span class=&o&&);&/span&
&span class=&k&&return&/span& &span class=&n&&webPageRepository&/span&&span class=&o&&.&/span&&span class=&na&&save&/span&&span class=&o&&(&/span&&span class=&n&&webPage&/span&&span class=&o&&);&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&h3&爬取页面&/h3&&p&刚刚说到,我们需要爬取的页面很多,因此我们使用多线程的方式来运行我们的代码,首先我们来将CrawlThread改写成线程的方式,核心代码如下:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&public&/span& &span class=&kd&&class&/span& &span class=&nc&&CrawlerThread&/span& &span class=&kd&&implements&/span& &span class=&n&&Runnable&/span& &span class=&o&&{&/span&
&span class=&nd&&@Override&/span&
&span class=&kd&&public&/span& &span class=&kt&&void&/span& &span class=&nf&&run&/span&&span class=&o&&()&/span& &span class=&o&&{&/span&
&span class=&k&&while&/span& &span class=&o&&(&/span&&span class=&kc&&true&/span&&span class=&o&&)&/span& &span class=&o&&{&/span&
&span class=&n&&WebPage&/span& &span class=&n&&webPage&/span& &span class=&o&&=&/span& &span class=&n&&crawlerService&/span&&span class=&o&&.&/span&&span class=&na&&getUnCrawlPage&/span&&span class=&o&&();&/span& &span class=&c1&&// TODO: 更好的退出机制&/span&
&span class=&k&&if&/span& &span class=&o&&(&/span&&span class=&n&&webPage&/span& &span class=&o&&==&/span& &span class=&kc&&null&/span&&span class=&o&&)&/span&
&span class=&k&&return&/span&&span class=&o&&;&/span& &span class=&c1&&// 拿不到url,说明没有需要爬的url,直接退出&/span&
&span class=&k&&try&/span& &span class=&o&&{&/span&
&span class=&k&&if&/span& &span class=&o&&(&/span&&span class=&n&&fetchHtml&/span&&span class=&o&&(&/span&&span class=&n&&webPage&/span&&span class=&o&&))&/span&
&span class=&n&&parse&/span&&span class=&o&&(&/span&&span class=&n&&webPage&/span&&span class=&o&&);&/span&
&span class=&o&&}&/span& &span class=&k&&catch&/span& &span class=&o&&(&/span&&span class=&n&&Exception&/span& &span class=&n&&e&/span&&span class=&o&&)&/span& &span class=&o&&{}&/span&
&span class=&o&&}&/span&
&span class=&o&&}&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&在CrawlerService中,我们还需要提供一个启动爬虫的入口:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&kd&&public&/span& &span class=&kt&&void&/span& &span class=&nf&&crawl&/span&&span class=&o&&()&/span& &span class=&kd&&throws&/span& &span class=&n&&InterruptedException&/span& &span class=&o&&{&/span&
&span class=&n&&ExecutorService&/span& &span class=&n&&executorService&/span& &span class=&o&&=&/span& &span class=&n&&Executors&/span&&span class=&o&&.&/span&&span class=&na&&newFixedThreadPool&/span&&span class=&o&&(&/span&&span class=&n&&MAX_THREADS&/span&&span class=&o&&);&/span&
&span class=&k&&for&/span&&span class=&o&&(&/span&&span class=&kt&&int&/span& &span class=&n&&i&/span& &span class=&o&&=&/span& &span class=&mi&&0&/span&&span class=&o&&;&/span& &span class=&n&&i&/span& &span class=&o&&&&/span& &span class=&n&&MAX_THREADS&/span&&span class=&o&&;&/span& &span class=&n&&i&/span&&span class=&o&&++)&/span& &span class=&o&&{&/span&
&span class=&n&&executorService&/span&&span class=&o&&.&/span&&span class=&na&&execute&/span&&span class=&o&&(&/span&&span class=&k&&new&/span& &span class=&n&&CrawlerThread&/span&&span class=&o&&(&/span&&span class=&k&&this&/span&&span class=&o&&));&/span&
&span class=&o&&}&/span&
&span class=&n&&executorService&/span&&span class=&o&&.&/span&&span class=&na&&shutdown&/span&&span class=&o&&();&/span&
&span class=&n&&executorService&/span&&span class=&o&&.&/span&&span class=&na&&awaitTermination&/span&&span class=&o&&(&/span&&span class=&n&&Long&/span&&span class=&o&&.&/span&&span class=&na&&MAX_VALUE&/span&&span class=&o&&,&/span& &span class=&n&&TimeUnit&/span&&span class=&o&&.&/span&&span class=&na&&DAYS&/span&&span class=&o&&);&/span&
&span class=&n&&Ehcache&/span& &span class=&n&&ehcache&/span& &span class=&o&&=&/span& &span class=&n&&cacheManager&/span&&span class=&o&&.&/span&&span class=&na&&getEhcache&/span&&span class=&o&&(&/span&&span class=&n&&cacheName&/span&&span class=&o&&);&/span&
&span class=&n&&ehcache&/span&&span class=&o&&.&/span&&span class=&na&&removeAll&/span&&span class=&o&&();&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&这样,爬虫的所有核心代码就搞定了,先运行CrawlerService.init()方法初始化爬虫队列,之后运行CrawlerService.crawl()就能让我们的爬虫跑起来啦。&/p&&h2&提供WEB应用&/h2&&p&之前我们提到,我们还要使用Spring MVC,通过Spring MVC,我们就能很方便的提供爬虫管理的API啦。更深入地学习Spring MVC,请大家参考&a href=&http://link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring MVC实战入门训练&/a&。&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&nd&&@RestController&/span&
&span class=&kd&&public&/span& &span class=&kd&&class&/span& &span class=&nc&&CrawlerController&/span& &span class=&o&&{&/span&
&span class=&nd&&@Autowired&/span&
&span class=&kd&&private&/span& &span class=&n&&CrawlerService&/span& &span class=&n&&crawlerService&/span&&span class=&o&&;&/span&
&span class=&nd&&@Value&/span&&span class=&o&&(&/span&&span class=&s&&&${auth.key}&&/span&&span class=&o&&)&/span&
&span class=&kd&&private&/span& &span class=&n&&String&/span& &span class=&n&&key&/span&&span class=&o&&;&/span&
&span class=&nd&&@ModelAttribute&/span&
&span class=&kd&&public&/span& &span class=&kt&&void&/span& &span class=&nf&&AuthConfig&/span&&span class=&o&&(&/span&&span class=&nd&&@RequestParam&/span& &span class=&n&&String&/span& &span class=&n&&auth&/span&&span class=&o&&)&/span& &span class=&kd&&throws&/span& &span class=&n&&AccessException&/span& &span class=&o&&{&/span&
&span class=&k&&if&/span&&span class=&o&&(!&/span&&span class=&n&&key&/span&&span class=&o&&.&/span&&span class=&na&&equals&/span&&span class=&o&&(&/span&&span class=&n&&auth&/span&&span class=&o&&))&/span& &span class=&o&&{&/span&
&span class=&k&&throw&/span& &span class=&k&&new&/span& &span class=&n&&AccessException&/span&&span class=&o&&(&/span&&span class=&s&&&auth failed&&/span&&span class=&o&&);&/span&
&span class=&o&&}&/span&
&span class=&o&&}&/span&
&span class=&nd&&@GetMapping&/span&&span class=&o&&(&/span&&span class=&s&&&/init&&/span&&span class=&o&&)&/span&
&span class=&kd&&public&/span& &span class=&kt&&void&/span& &span class=&nf&&init&/span&&span class=&o&&()&/span& &span class=&o&&{&/span&
&span class=&n&&crawlerService&/span&&span class=&o&&.&/span&&span class=&na&&init&/span&&span class=&o&&();&/span&
&span class=&o&&}&/span&
&span class=&nd&&@GetMapping&/span&&span class=&o&&(&/span&&span class=&s&&&/crawl&&/span&&span class=&o&&)&/span&
&span class=&kd&&public&/span& &span class=&kt&&void&/span& &span class=&nf&&crawl&/span&&span class=&o&&()&/span& &span class=&kd&&throws&/span& &span class=&n&&InterruptedException&/span& &span class=&o&&{&/span&
&span class=&n&&crawlerService&/span&&span class=&o&&.&/span&&span class=&na&&crawl&/span&&span class=&o&&();&/span&
&span class=&o&&}&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&启动后,按顺序访问&a href=&http://link.zhihu.com/?target=http%3A//localhost%3A8080/init%26auth%3Dxxx& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&localhost:8080/init&aut&/span&&span class=&invisible&&h=xxx&/span&&span class=&ellipsis&&&/span&&/a&和&a href=&http://link.zhihu.com/?target=http%3A//localhost%3A8080/crawl%26auth%3Dxxx& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&localhost:8080/crawl&au&/span&&span class=&invisible&&th=xxx&/span&&span class=&ellipsis&&&/span&&/a&即可,注意,这里的xxx是自己设置的密码,大家可以在application.properties里自行修改。&/p&&p&最后,我们将所有爬取到的音乐通过页面展示出来:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&nd&&@Controller&/span&
&span class=&kd&&public&/span& &span class=&kd&&class&/span& &span class=&nc&&SongController&/span& &span class=&o&&{&/span&
&span class=&nd&&@Autowired&/span& &span class=&n&&SongRepository&/span& &span class=&n&&songRepository&/span&&span class=&o&&;&/span&
&span class=&nd&&@GetMapping&/span&&span class=&o&&(&/span&&span class=&s&&&/songs&&/span&&span class=&o&&)&/span&
&span class=&kd&&public&/span& &span class=&n&&String&/span& &span class=&nf&&songs&/span&&span class=&o&&(&/span&&span class=&n&&Model&/span& &span class=&n&&model&/span&&span class=&o&&,&/span&
&span class=&nd&&@PageableDefault&/span&&span class=&o&&(&/span&&span class=&n&&size&/span& &span class=&o&&=&/span& &span class=&mi&&100&/span&&span class=&o&&,&/span& &span class=&n&&sort&/span& &span class=&o&&=&/span& &span class=&s&&&commentCount&&/span&&span class=&o&&,&/span& &span class=&n&&direction&/span& &span class=&o&&=&/span& &span class=&n&&Sort&/span&&span class=&o&&.&/span&&span class=&na&&Direction&/span&&span class=&o&&.&/span&&span class=&na&&DESC&/span&&span class=&o&&)&/span& &span class=&n&&Pageable&/span& &span class=&n&&pageable&/span&&span class=&o&&)&/span& &span class=&o&&{&/span&
&span class=&n&&model&/span&&span class=&o&&.&/span&&span class=&na&&addAttribute&/span&&span class=&o&&(&/span&&span class=&s&&&songs&&/span&&span class=&o&&,&/span& &span class=&n&&songRepository&/span&&span class=&o&&.&/span&&span class=&na&&findAll&/span&&span class=&o&&(&/span&&span class=&n&&pageable&/span&&span class=&o&&));&/span&
&span class=&k&&return&/span& &span class=&s&&&songs&&/span&&span class=&o&&;&/span&
&span class=&o&&}&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&这样,我们的整个爬虫就完成了,整个应用是通过Spring Boot运行的,感兴趣的话可以参考&a href=&http://link.zhihu.com/?target=https%3A//www.tianmaying.com/tutorial/spring-boot-overview& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring Boot——开发新一代Spring Java应用&/a&。&/p&&h2&后续&/h2&&h3&爬取效率&/h3&&p&爬虫爬了两天后,一共爬到了573945条数据,此时数据库访问速度已经变成龟速... 事实证明,对于大型爬虫而言,这样简单粗暴的将数据库作为爬虫队列是不科学的,简单想了一下,我们可以用下列方式来优化爬虫的效率:&/p&&ul&&li&将webpage表分拆成playlist、album、song三张表,按照数据顺序先爬playlist,再爬album,最后再爬song(甚至将song拆成多张表)&/li&&li&由于网易云音乐的各种对象都有id,将id作为索引,提高mysql的效率&/li&&li&获取url的时候按照id从小到大获取,获取完一条删除一条&/li&&li&既然mysql达不到我们的要求,可以考虑直接将mysql替换掉,使用redis作为爬虫队列&/li&&/ul&&p&优化的方式有很多种,有些可以借助工具来实现,有些需要考虑具体的业务逻辑。这里我们不具体实现,感兴趣的同学可以自行实现,看看如何优化可以达到最大的效率。&/p&&h3&音乐页面访问效率&/h3&&p&数据量大了之后,影响的不仅仅是爬虫爬的效率,当然还有访问音乐列表的速度,随意访问一个页面都需要4秒左右。最后,我通过缓存解决了这个问题,具体实现我们也不多讲了,可以参考文章&a href=&http://link.zhihu.com/?target=https%3A//www.tianmaying.com/tutorial/spring-web-ehcache& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&基于Spring的缓存&/a&。加上缓存之后页面访问速度达到了100ms左右。&/p&&h3&数据更新&/h3&&p&除了爬虫的爬取效率外,还有一个很重要环节,就是数据的更新,评论数据是每天都会变化的,我们的数据当然也要每天更新。这里,我们使用最简单粗暴的方式,建立一个定时任务(有关定时任务可以参考&a href=&http://link.zhihu.com/?target=https%3A//www.tianmaying.com/tutorial/spring-scheduling-task& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&基于Spring Boot的定时任务&/a&),在每天的凌晨1点,找到评论数量大于5000的歌曲,将其状态设置为uncrawl(未爬),启动爬虫即可:&/p&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&nd&&@GetMapping&/span&&span class=&o&&(&/span&&span class=&s&&&/update&&/span&&span class=&o&&)&/span&
&span class=&nd&&@Scheduled&/span&&span class=&o&&(&/span&&span class=&n&&cron&/span& &span class=&o&&=&/span& &span class=&s&&&0 1 0 * * ?&&/span&&span class=&o&&)&/span&
&span class=&kd&&public&/span& &span class=&kt&&void&/span& &span class=&nf&&update&/span&&span class=&o&&()&/span& &span class=&kd&&throws&/span& &span class=&n&&InterruptedException&/span& &span class=&o&&{&/span&
&span class=&n&&crawlerService&/span&&span class=&o&&.&/span&&span class=&na&&update&/span&&span class=&o&&();&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-java&&&span&&/span&&span class=&nd&&@Async&/span&
&span class=&kd&&public&/span& &span class=&kt&&void&/span& &span class=&nf&&update&/span&&span class=&o&&()&/span& &span class=&kd&&throws&/span& &span class=&n&&InterruptedException&/span& &span class=&o&&{&/span&
&span class=&n&&List&/span&&span class=&o&&&&/span&&span class=&n&&Song&/span&&span class=&o&&&&/span& &span class=&n&&webPages&/span& &span class=&o&&=&/span& &span class=&n&&songRepository&/span&&span class=&o&&.&/span&&span class=&na&&findByCommentCountGreaterThan&/span&&span class=&o&&(&/span&&span class=&mi&&5000L&/span&&span class=&o&&);&/span&
&span class=&n&&webPages&/span&&span class=&o&&.&/span&&span class=&na&&forEach&/span&&span class=&o&&(&/span&&span class=&n&&s&/span& &span class=&o&&-&&/span& &span class=&o&&{&/span&
&span class=&n&&WebPage&/span& &span class=&n&&p&/span& &span class=&o&&=&/span& &span class=&n&&webPageRepository&/span&&span class=&o&&.&/span&&span class=&na&&findOne&/span&&span class=&o&&(&/span&&span class=&n&&s&/span&&span class=&o&&.&/span&&span class=&na&&getUrl&/span&&span class=&o&&());&/span&
&span class=&n&&p&/span&&span class=&o&&.&/span&&span class=&na&&setStatus&/span&&span class=&o&&(&/span&&span class=&n&&Status&/span&&span class=&o&&.&/span&&span class=&na&&uncrawl&/span&&span class=&o&&);&/span&
&span class=&n&&webPageRepository&/span&&span class=&o&&.&/span&&span class=&na&&save&/span&&span class=&o&&(&/span&&span class=&n&&p&/span&&span class=&o&&);&/span&
&span class=&o&&});&/span&
&span class=&n&&crawl&/span&&span class=&o&&();&/span&
&span class=&o&&}&/span&
&/code&&/pre&&/div&&p&整个站点是用Spring MVC假设的,学习Spring MVC,请大家参考和&a href=&http://link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring MVC实战入门训练&/a&和&a href=&http://link.zhihu.com/?target=http%3A//www.tianmaying.com/tutorial/spring-mvc-quickstart& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring MVC的入门实例&/a&。&/p&&p&希望进一步深入了解的同学请参考&a href=&http://link.zhihu.com/?target=https%3A//course.tianmaying.com/music-163-crawler& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&一起来写网易云音乐Java爬虫&/a&&/p&&br&&h2&进一步阅读&/h2&&p&&a href=&http://link.zhihu.com/?target=http%3A//www.tianmaying.com/tutorial/spring-mvc-quickstart& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring MVC的入门实例&/a&。&/p&&p&更深入地学习Spring MVC,请大家参考&a href=&http://link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring MVC实战入门训练&/a&。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-cf27e09ef68d5f_b.png& data-rawwidth=&600& data-rawheight=&233& class=&origin_image zh-lightbox-thumb& width=&600& data-original=&https://pic4.zhimg.com/v2-cf27e09ef68d5f_r.jpg&&&/figure&&p&欢迎关注天码营微信公众号: TMY-EDU&/p&&p&小编重点推荐:&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&打造功能完整的博客系统:Spring MVC实战入门&/a&&br&&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-mvc-mybatis-qa& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&开发问答网站:基于MyBatis和Spring MVC&/a&&br&&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//course.tianmaying.com/java-snake& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Java贪吃蛇的设计与实现&/a&&br&&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//course.tianmaying.com/spring-data-jpa& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Spring Data JPA实战入门训练&/a&&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//course.tianmaying.com/full-stack-java-web-development& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&Java Web实战训练&/a&&/p&&p&更多精彩内容请访问&a href=&http://link.zhihu.com/?target=http%3A//www.tianmaying.com/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&天码营网站&/a&&/p&
由发表在 起因前两天在知乎上看到一个帖子《》,一时技痒,用Java实现了一个简单的爬虫,这里简单记录一下。最终的结果开放出来了,大家可以随意访问,请戳这里&&&&&& 。爬虫简介网络爬虫是…
&figure&&img src=&https://pic4.zhimg.com/v2-b9b6619beb4473dac759e3_b.jpg& data-rawwidth=&480& data-rawheight=&369& class=&origin_image zh-lightbox-thumb& width=&480& data-original=&https://pic4.zhimg.com/v2-b9b6619beb4473dac759e3_r.jpg&&&/figure&&p&&b&作者:Pharisees@白鹅纪&/b&&/p&&p&想必每个推理故事的读者都曾设想过自己有天卷入一场犯罪事件中的场景吧:要么是作为侦探,破解罪犯的诡计,要么干脆化身邪恶,构造一场“完美犯罪”——不过当然,都只是想想而已。而今天要推荐的这本漫画《My Home Hero》的主角鸟栖哲雄,也是这样一位普通的中年上班族兼推理爱好者,偶尔写写没人看的推理小说就是他最大的满足了。他怎么也不会想到,有一天自己会真正卷入一场杀人事件中……&/p&&figure&&img src=&https://pic4.zhimg.com/v2-e8ae1c4c6f693b8b04ab83c07fd1df63_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&720& data-rawheight=&1034& class=&origin_image zh-lightbox-thumb& width=&720& data-original=&https://pic4.zhimg.com/v2-e8ae1c4c6f693b8b04ab83c07fd1df63_r.jpg&&&/figure&&h2&&b&极限智斗,《死亡笔记》接班人&/b&&/h2&&p&拥有一个普通而幸福的家庭的鸟栖哲雄某天意外发现女儿被混混男友殴打了,气愤不已的他在调查时又意外得知这个渣男正在谋划杀害自己的女儿,一怒之下鸟栖先下手为强将其杀害。然而他不知道的是,这个混混却是反派Boss珍视的儿子……&/p&&figure&&img src=&https://pic2.zhimg.com/v2-3ef4eebdd1b9ffacdf631_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&1782& data-rawheight=&1280& class=&origin_image zh-lightbox-thumb& width=&1782& data-original=&https://pic2.zhimg.com/v2-3ef4eebdd1b9ffacdf631_r.jpg&&&/figure&&p&《My Home Hero》的故事本身十分普通:鸟栖哲雄为了保护家庭与黑社会斗智斗勇。但智商极高行动力爆表的主角,和他旗鼓相当的对手一起,为这样一个普通的故事制造出了极端惊险刺激的张力。作为一个资深推理迷,鸟栖哲雄完美地将各种犯罪、反侦察知识运用到了实践中,从尸体、尸臭的处理到编造证词、误导调查,他几乎没有留下任何证据。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-a7a076fcb_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&946& data-rawheight=&1360& class=&origin_image zh-lightbox-thumb& width=&946& data-original=&https://pic4.zhimg.com/v2-a7a076fcb_r.jpg&&&/figure&&figure&&img src=&https://pic1.zhimg.com/v2-943cfbd3eb4ea4646fe74_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&891& data-rawheight=&1280& class=&origin_image zh-lightbox-thumb& width=&891& data-original=&https://pic1.zhimg.com/v2-943cfbd3eb4ea4646fe74_r.jpg&&&/figure&&p&但黑帮方面主导调查的恭一也并非等闲之辈,果断的性格、特工一般的调查手段以及敏锐的直觉让他始终对表现过于完美的鸟栖疑虑重重紧追不舍,智商在线的双方交锋不断,稍有差池便是死路一条,这样环环相扣的极限智斗上次看到还是在《死亡笔记》里,而本作中势单力薄的普通人对抗心狠手辣的黑帮——双方力量差距带来的压迫感甚至更胜一筹。&/p&&figure&&img src=&https://pic3.zhimg.com/v2-653fca7c009b567ff865ee2e_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&720& data-rawheight=&1034& class=&origin_image zh-lightbox-thumb& width=&720& data-original=&https://pic3.zhimg.com/v2-653fca7c009b567ff865ee2e_r.jpg&&&/figure&&h2&&b&血浓于水,最是患难见真情&/b&&/h2&&p&作为一部现实题材的犯罪漫画,剧情之外,真实感的营造对观感也有很大影响。《My Home Hero》能将充满非现实感的的剧情抒写得真实可信,最大的秘诀在于对角色情感的深入刻画。&/p&&p&正如漫画标题所说,“家庭”是这个故事的核心:一方面,鸟栖哲雄杀人是为了保护自己的女儿,而他的妻子得知真相后果断的和丈夫站在一起守护这个家庭:夫妻二人并非天生的犯罪者,也不是没有过动摇:&/p&&figure&&img src=&https://pic1.zhimg.com/v2-cd8ddedfd748e5da6826430_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&720& data-rawheight=&1034& class=&origin_image zh-lightbox-thumb& width=&720& data-original=&https://pic1.zhimg.com/v2-cd8ddedfd748e5da6826430_r.jpg&&&/figure&&figure&&img src=&https://pic3.zhimg.com/v2-403b409ad362da31f434af9b6bc7210e_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&720& data-rawheight=&1035& class=&origin_image zh-lightbox-thumb& width=&720& data-original=&https://pic3.zhimg.com/v2-403b409ad362da31f434af9b6bc7210e_r.jpg&&&/figure&&p&但血缘纽带的支撑最终让他们爆发出了超越常人的勇气与智慧,也合理地抹平了“普通人”与“黑帮”之间天堑一般的力量差距,也让故事变得真实可信起来。&/p&&figure&&img src=&https://pic2.zhimg.com/v2-a73c9df85e71_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&720& data-rawheight=&1034& class=&origin_image zh-lightbox-thumb& width=&720& data-original=&https://pic2.zhimg.com/v2-a73c9df85e71_r.jpg&&&/figure&&figure&&img src=&https://pic4.zhimg.com/v2-c2af8a3afb0be79893c15f_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&720& data-rawheight=&1034& class=&origin_image zh-lightbox-thumb& width=&720& data-original=&https://pic4.zhimg.com/v2-c2af8a3afb0be79893c15f_r.jpg&&&/figure&&p&但另一方面,反派Boss对其死去儿子狂热的家族爱较之主角方也丝毫不弱,这份扭曲的爱在其子死后化为了无穷的怒火,给每个人带去了强大的压迫感。&/p&&figure&&img src=&https://pic4.zhimg.com/v2-1d6cc2a9d9f945209ddf5bf5ec819577_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&720& data-rawheight=&517& class=&origin_image zh-lightbox-thumb& width=&720& data-original=&https://pic4.zhimg.com/v2-1d6cc2a9d9f945209ddf5bf5ec819577_r.jpg&&&/figure&&p&台面上的角色们拼尽全力斗智斗勇,无非是在祈祷这份怒火,及其带来的死亡不要落在自己头上。扣人心弦的智斗之下,真正的战斗发生在这两种截然相反却同样热烈的激情之间:守护与复仇,究竟哪一方能获得最终的胜利,又会付出怎样的代价?就请各位读者亲自去漫画中寻找答案吧!&/p&&h2&&b&更多精彩内容,欢迎关注【白鹅纪】微信公众号!&/b&&/h2&
作者:Pharisees@白鹅纪想必每个推理故事的读者都曾设想过自己有天卷入一场犯罪事件中的场景吧:要么是作为侦探,破解罪犯的诡计,要么干脆化身邪恶,构造一场“完美犯罪”——不过当然,都只是想想而已。而今天要推荐的这本漫画《My Home Hero》的主角鸟栖…
&figure&&img src=&https://pic3.zhimg.com/v2-ec953dae6b67c8b_b.jpg& data-rawwidth=&1068& data-rawheight=&298& class=&origin_image zh-lightbox-thumb& width=&1068& data-original=&https://pic3.zhimg.com/v2-ec953dae6b67c8b_r.jpg&&&/figure&&p&最近看到一个知乎的问题:为什么知乎大V好像什么都懂?这个问题下,知乎大v们能有一千零一个理论,角度和抖机灵来告诉你,为什么知乎大V好像什么都懂。&/p&&p&虽然大部分知乎大v如你我一样,都是普通人,有很多抖机灵,搬段子,写鸡汤的大V们也不见得学识多么丰富。但是,我确实有幸在知乎上认识一些朋友,他们的学识,以及阅读品味,以及由此带来的视角和思维深度,确实要比大部分人高上许多。&/p&&p&尤其是,当有幸遇见了一些很棒的同龄人,和他们的交流,会真的让我觉得,我过去二十多年的时间真的是喂了狗了。喂狗了是因为,自己的阅读质量太低了。&/p&&p&&b&这种阅读质量的底,体现在阅读数量和方法上面,但是更重要的是,体现在阅读材料的选择上面。即,浪费了太多的时间在阅读信息量低的,零散的,不构成科学的系统性认知的书籍上面。&/b&&/p&&p&自从意识到英语真的可以给我打开更大的世界,获得更高质量的信息的时候,我便在这条路上停不下来了,虽然走得还不够远。但是我想,我是值得更好的阅读质量,更棒的精神生活的。&/p&&p&回想起来,自己以前同样读心理学的书籍,外面去搜书单,都是些比如《遇见更好的自己》这样外行人写的不伦不类的二手甚至三手信息,里面充斥了大量的心灵鸡汤,以及没有完整的学科知识支撑的作者臆想。而这样的书籍,在对心理学没有基本的科学认识的时候,是很容易没误导的,读了书浪费时间还好,如果读歪了,走上所谓的心灵灵修的道路,那真的是得不偿失了。&/p&&p&现在看来,如果我对心理学有基本的兴趣,并且认为自己有阅读的必要,以帮助我实现更好的自我认识和成长,那么我会去读比如:&/p&&p&Gross, R. (2010). &i&Psychology: The Science of Mind&br&and Behavior&/i&, 6th Ed. Hodder Education.&/p&&p&这本书是剑桥大学的教育和心理学推荐给本科入学新生的读物。这些新被剑桥大学录取的学生,学校官方网站说了,并不需要他们提前具备心相关专业方面的各种知识。也就是说,这些书单,对于没有阅读基础的你我来说,应该是不构成专业上的阅读障碍的。&/p&&p&说到这里,我自己都忍不住为自己的机智点赞了,&b&从各大名校挂出来的给本科生的阅读清单入手,用这种方法去获得认知一个学科的基础,构建知识体系,应该是最安全便捷的途径了。&/b&与其被网络上各种卖成功学和畅销鸡汤的书单坑,或者厚着脸皮求大牛推荐(大牛有时候拿不准你的水平,下手会过重,吓到你)不如直接去各大名校官网去搜好了。名校给本科生开的书单,既保证了科学性和严谨性,并且还不要求学科基础。&/p&&p&本来这篇文章,想直接把各个学科的reading list都列出来的,但是想想,每个人的兴趣和爱好肯定不一样,比如我想读哲学和心理学的书,对生物学此生都没有阅读的兴趣,化学和材料也是,但是你未必如是。&/p&&p&故,我在这里把各官网的reading list的网址分享出来,当然,探索这些官网,可能对你的英语能力有一些要求,而阅读这些英文书籍更是。不过有很多书可以搜到中文版本,或者搜索著书的作者,可以其他中文翻译的作品,学科种类繁多,今日不能一一列出,以后我会在我的公众号上慢慢整理出书单出来。&/p&&p&今天只是把几个重点的书单网址贴出来,大家可以自己去搜,不需要翻墙。&/p&&p&1. King’s college(剑桥大学国王学院)推荐阅读书单&/p&&p&&a href=&http://link.zhihu.com/?target=http%3A//www.kings.cam.ac.uk/study/undergraduate/offerholders/reading-lists/index.html& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&kings.cam.ac.uk/study/u&/span&&span class=&invisible&&ndergraduate/offerholders/reading-lists/index.html&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&2. Downing college Combridge 的阅读推荐,不仅有按学科的本科新生阅读书,还有培养计划呢,可以看看剑桥的本科培养大概是什么样子的,比如,我还在他们的哲学院系下找到了一份官方的写作训练资料,是为了培养本科生的学术写作能力用的,真的很棒啊。&/p&&p&&a href=&http://link.zhihu.com/?target=http%3A//www.dow.cam.ac.uk/join-downing/information-new-students/undergraduates-reading-lists& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&dow.cam.ac.uk/join-down&/span&&span class=&invisible&&ing/information-new-students/undergraduates-reading-lists&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&3. Wolfson College(学科基本和国王学院重合),不知道书单是否一样&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//www.wolfson.cam.ac.uk/applying/undergraduate/offerholders/reading& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://www.&/span&&span class=&visible&&wolfson.cam.ac.uk/apply&/span&&span class=&invisible&&ing/undergraduate/offerholders/reading&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&4. 牛津大学的各个学科reading list&/p&&p&&a href=&http://link.zhihu.com/?target=http%3A//www.oxbridgeapplications.com/resources_category/reading-lists/%3Fgclid%3DCPbQupzFzNYCFdgnvQodlZcAIQ& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://www.&/span&&span class=&visible&&oxbridgeapplications.com&/span&&span class=&invisible&&/resources_category/reading-lists/?gclid=CPbQupzFzNYCFdgnvQodlZcAIQ&/span&&span class=&ellipsis&&&/span&&/a&&/p&&figure&&img src=&https://pic3.zhimg.com/v2-bd2cb6acecb19e411552_b.jpg& data-caption=&& data-size=&normal& data-rawwidth=&316& data-rawheight=&392& class=&content_image& width=&316&&&/figure&&p&(这张截图放的是数学这门学科的reading list的推荐,点开进去要简单注册一下…)&/p&&p&5. 哈佛最新放出来的夏季假期阅读清单,什么学科的都有,真的是,很长…..&/p&&p&&a href=&http://link.zhihu.com/?target=https%3A//sites.fas.harvard.edu/%7Esica/reading.htm& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&sites.fas.harvard.edu/~&/span&&span class=&invisible&&sica/reading.htm&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&还有一个JULY版本的阅读推荐,发现这些学校的图书馆的官网还会定期发布阅读推荐,也是一个寻找阅读信息的好的地方啊。&a href=&http://link.zhihu.com/?target=https%3A//gsas.harvard.edu/news/colloquy/summer-2017/reading-list-july-2017& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&https://&/span&&span class=&visible&&gsas.harvard.edu/news/c&/span&&span class=&invisible&&olloquy/summer-2017/reading-list-july-2017&/span&&span class=&ellipsis&&&/span&&/a&&/p&&p&其他几个学校也特意去搜了,目前有点混乱,我要去吃饭了,回头把书单整理整理放到和专栏同名的公众号里。&/p&&p&还有昨天推荐的这套书牛津通识系列,&a href=&https://zhuanlan.zhihu.com/p/& class=&internal&&当牛津为了人类科普操碎了心,就有了这套此生不读会后悔的书&/a&(去公众号&b&杨大宝识&/b&回复“1”,就能直接获得下载),全英文原版,快戳。&/p&&p&&br&&/p&&hr&&p&最后,关注&b&杨大宝识(yangdabaoshi):读书改变命运,英语打开世界。&/b&&/p&&p&&br&&/p&&p&&b&在这里分享免费的英语学习资源,希望大家都能够更好的未来。&/b&&/p&
最近看到一个知乎的问题:为什么知乎大V好像什么都懂?这个问题下,知乎大v们能有一千零一个理论,角度和抖机灵来告诉你,为什么知乎大V好像什么都懂。虽然大部分知乎大v如你我一样,都是普通人,有很多抖机灵,搬段子,写鸡汤的大V们也不见得学识多么丰富…
奇异人生life is strange&br&不是玩儿到最后会哭,是我现在打下Chloe的名字我就会哭。&br&玩儿游戏初期,我心里一边儿埋怨Chloe太能惹事儿了,一边儿拼了命地救她,我还以为最后会有个大团圆结局,结果制作组就是这么恶意满满,偏偏就要你在“救一个你最心爱的人”和“救一群无辜的人”当中选择。&br&&figure&&img data-rawheight=&1152& src=&https://pic1.zhimg.com/v2-e24c134bddfe583a30884_b.png& data-rawwidth=&2048& class=&origin_image zh-lightbox-thumb& width=&2048& data-original=&https://pic1.zhimg.com/v2-e24c134bddfe583a30884_r.png&&&/figure&&br&也许你会说,这有什么好选的?肯定救最爱的人啊,那这就是制作组最过分的地方了,整个游戏前期你会不停地和这个小镇的各种人说话交流获取信息,让你对这个小镇每一个人都有了解,让你觉得他们是真的有血有肉拥有独立个性的存在而不是简单的NPC,外加后期剧情的深入,让你逐渐理解主角Max和Chloe的羁绊,理解Chloe是为什么变得如此没有安全感,并且在最终选择之前会给你来一大段回忆杀,让你哭得不能自已,导致你对每一个人都有了感情,而不敢盲目地作出牺牲谁的决定。&br&于是,在我边哭边犹豫了30分钟,痛下决心选了牺牲Chloe去救整个小镇。&br&嗯,所以时间回溯到了Chole和Max多年后的再度重逢前,即整个游戏的起点。&br&&figure&&img data-rawheight=&1152& src=&https://pic3.zhimg.com/v2-de99e7adcda_b.png& data-rawwidth=&2048& class=&origin_image zh-lightbox-thumb& width=&2048& data-original=&https://pic3.zhimg.com/v2-de99e7adcda_r.png&&&/figure&&br&Max眼睁睁地看着Chole死在了Nathan枪下,独自一人承载着和Chole这五天的全部的美好回忆,救下了整个小镇。&br&&br&&br&要我说这个游戏真的太“残忍”了,对于Max(即玩家),让你深深地感受到一种无能为力,你拥有的能力越强大责任就越重,因为现实就是这样,你根本不可能顾全所有。对于Chole,她失去了亲人,曾经最好的朋友(Max)也在她父亲过世后离开,和继父相处极差,好不容易交到了新的朋友(Rachel)也特么从游戏一开始就告知你她已经失踪了八个月。你说惨不惨,就问你惨不惨。&br&&br&&br&具体的我就不剧透了,真的建议大家去玩儿一玩儿这个游戏,不然你们都对不起我一边儿打字一边儿掉的这些眼泪(不。&br&总之,这个游戏剧情和感情都融合的很好很丰富,如果拍成美剧收视率应该会很高,融合了情感、科幻、悬疑、惊悚为一体。&br&&br&游戏音乐也很好听,我现在单曲循环都能哭出来(让我心塞的是,这个游戏的音乐被国内的某个综艺节目用过后,网易云的评论一度沦陷,还有一群人在评论里刷薛之谦,导致我现在整个人都:?????因为真的希望更多的人是因为游戏而认识的这些歌,可能是我对它执拗的偏爱吧(逃。&br&&br&最后发几张游戏截图:&br&&figure&&img data-rawheight=&1152& src=&https://pic3.zhimg.com/v2-830f60edb64a620bcb06536_b.png& data-rawwidth=&2048& class=&origin_image zh-lightbox-thumb& width=&2048& data-original=&https://pic3.zhimg.com/v2-830f60edb64a620bcb06536_r.png&&&/figure&&br&&figure&&img data-rawheight=&1152& src=&https://pic4.zhimg.com/v2-eb016c56753b78aaf5c6d46a_b.png& data-rawwidth=&2048& class=&origin_image zh-lightbox-thumb& width=&2048& data-original=&https://pic4.zhimg.com/v2-eb016c56753b78aaf5c6d46a_r.png&&&/figure&&br&&figure&&img data-rawheight=&800& src=&https://pic3.zhimg.com/v2-60c38f5c30c_b.jpg& data-rawwidth=&1280& class=&origin_image zh-lightbox-thumb& width=&1280& data-original=&https://pic3.zhimg.com/v2-60c38f5c30c_r.jpg&&&/figure&&br&&figure&&img data-rawheight=&1023& src=&https://pic2.zhimg.com/v2-12bc90dfb5e6fe70c8a1751_b.png& data-rawwidth=&1909& class=&origin_image zh-lightbox-thumb& width=&1909& data-original=&https://pic2.zhimg.com/v2-12bc90dfb5e6fe70c8a1751_r.png&&&/figure&&br&&br&再撒一把又甜又虐心的狗粮:&br&&figure&&img data-rawheight=&1152& src=&https://pic2.zhimg.com/v2-7f621be89f2bf4cb807d_b.png& data-rawwidth=&2048& class=&origin_image zh-lightbox-thumb& width=&2048& data-original=&https://pic2.zhimg.com/v2-7f621be89f2bf4cb807d_r.png&&&/figure&&br&&figure&&img data-rawheight=&1152& src=&https://pic3.zhimg.com/v2-264d00d6233a1caf0530e_b.png& data-rawwidth=&2048& class=&origin_image zh-lightbox-thumb& width=&2048& data-original=&https://pic3.zhimg.com/v2-264d00d6233a1caf0530e_r.png&&&/figure&&br&&br&嗯,就以上这么多吧,因为看到这个问题太激动了所以直接拿手机打的,玩儿过的同样感同身受的记得点个赞,没玩儿过的打算去尝试的也给个赞嗷。&br&&br&顺便,这个游戏出了前传,即Chole和Rachel的故事,好像刚刚出完第一章,Steam上有售。我暂时还没玩儿,因为还没调整好心态,玩儿完这个游戏我崩溃了好几天,实在是怕前传依旧高虐…已经玩儿了的朋友不要给我剧透!!!!&br&&br&&b&& You are my number one priority now. You are all that matters to me. &&/b&&br&&b&& I know. You proved that over and over again...even though I don't deserve it. &

我要回帖

更多关于 hao 8198 123 的文章

 

随机推荐