北大青鸟华美官网:双十一就要来了,在举国一片“买买买”的呼声中,单身汪的咆哮声也愈发凄厉了。作为一个Python程序员,要如何找到小姐姐,避开暴击伤害,在智中取胜呢?于是就有了以下的对话:北大青鸟华美官网:北大青鸟华美官网:北大青鸟华美官网:~今天我们的目标是,爬社区的小姐姐~而且,我们又要用到新的姿势(雾)了~scrapy爬虫框架~本文主要讲scrapy框架的原理和使用,建议至少在理解掌握Python爬虫原理后再使用框架(不要问我为什么,我哭给你看)。scrapy原理在写过几个爬虫程序之后,我们就会知道,利用爬虫获取数据大概的步骤:请求网页。获取网页。匹配信息。下载数据。数据清洗。存入数据库。scrapy是一个很有名的爬虫框架,可以很方便的进行网页信息爬取。那么scrapy到底是如何工作的呢?之前在网上看了不少scrapy入门的教程,大多数入门教程都配有这张图。北大青鸟华美官网:也不知道是这张图实在太经典了,还是程序员们都懒得画图,我第一次看到这个图的时候,心情是这样的。经过了一番深入的理解,大概知道这幅图的意思,让我来举个栗子(是的,我又要举奇怪的栗子了):北大青鸟华美官网:原理图之我要吃好吃的当我们想吃东西的时候,我们会出门,走到街上,寻找一家想吃的店,然后点餐,服务员再通知厨房去做,最后菜到餐桌上,或者被打包带走。这就是爬虫程序在做的事,它要将所有获取数据需要进行的操作,都写好。而scrapy就像一个点餐APP一般的存在,在订餐列表(spiders)选取自己目标餐厅里想吃的菜(items),在收货(pipeline)处写上自己的收货地址(存储方式)。点餐系统(scrapyengine)会根据订餐情况要求商铺(Internet)的厨房(download)将菜做好,由于会产生多个外卖取货订单(request),系统会根据派单(schedule)分配外卖小哥从厨房取货(request)和送货(response)。说着说着我都饿了。。。。什么意思呢?在使用scrapy时,我们只需要设置spiders(想要爬取的内容),pipeline(数据的清洗,数据的存储方式),还有一个middlewares,是各功能间对接时的一些设置,就可以不用操心其他的过程,一切交给scrapy模块来完成。北大青鸟华美官网:之后,创建一个新项目:1.$scrapystartprojectzhihuxjj我用的是pycharm编译器,在spiders文件下创建zhihuxjj.py。在zhihuxjj.py这个文件中,我们要编写我们的爬取规则。爬取规则制定(spider)创建好了项目,让我们来看一下我们要吃的店和菜…哦不,要爬的网站和数据。我选用了知乎作为爬取平台,知乎是没有用户从1到n的序列id的,每个人可以设置自己的个人主页id,且为唯一。所以采选了一枚种子用户,爬取他的关注者,也可以关注者和粉丝一起爬,考虑到粉丝中有些三无用户,我仅选择了爬取关注者列表,再通过关注者主页爬取关注者的关注者,如此递归。北大青鸟华美官网:对于程序的设计,是这样的。北大青鸟华美官网:之后就是种子用户的个人主页,知乎粉丝多的大V很多,但是关注多的人就比较难发现了,这里我选择了知乎的黄继新,联合创始人,想必关注了不少优质用户(???)?。分析一下个人主页可知,个人主页由'用户id组成。我们要获取的信息是用callback回调函数(敲黑板!!划重点!!)的方式设计,这里一共设计了俩个回调函数:用户的关注列表和关注者的个人信息。使用chrome浏览器查看上图的页面可知获取关注列表的url,以及关注者的用户id。将鼠标放在用户名上,如下图:北大青鸟华美官网:,分析url可知:1.关注者列表链接构成:'用户id'+'/followees?include=data[*].answer_count,articles_count,gender,follower_count,is_followed,is_following,badge[?(type=best_answerer)].topics&offset=0&limit=20'2.个人信息链接构成:'用户id'+'?include=allow_message%2Cis_followed%2Cis_following%2Cis_org%2Cis_blocking%2Cemployments%2Canswer_count%2Cfollower_count%2Carticles_count%2Cgender%2Cbadge%5B%3F(type%3Dbest_answerer)%5D.topics'so,我们在上一节中创建的zhihuxjj.py文件中写入以下代码:1.importjson2.fromzhihuxjj.itemsimportZhihuxjjItem3.fromscrapyimportSpider,Request4.5.classZhihuxjjSpider(Spider):6.name='zhihuxjj'#scrapy用于区别其他spider的名字,具有唯一性。7.allowed_domains=[]#爬取范围8.start_urls=[]9.start_user=jixin北大青鸟华美官网:='{user}/followees?include=data[*].answer_count,articles_count,gender,follower_count,is_followed,is_following,badge[?(type=best_answerer)].topics&offset={offset}&limit=20'#关注列表网址11.user_url='{user}?include=locations,employments,gender,educations,business,voteup_count,thanked_Count,follower_count,following_count,cover_url,following_topic_count,following_question_count,following_favlists_count,following_columns_count,avatar_hue,answer_count,articles_count,pins_count,question_count,commercial_question_count,favorite_count,favorited_count,logs_count,marked_answers_count,marked_answers_text,message_thread_token,account_status,is_active,is_force_renamed,is_bind_sina,sina_weibo_url,sina_weibo_name,show_sina_weibo,is_blocking,is_blocked,is_following,is_followed,mutual_followees_count,vote_to_count,vote_from_count,thank_to_count,thank_from_count,thanked_count,description,hosted_live_count,participated_live_count,allow_message,industry_category,org_name,org_homepage,badge[?(type=best_answerer)].topics'#个人信息链接12.defstart_requests(self):13.yieldRequest(self.followees_url.format(user=self.start_user,offset=0),callback=self.parse_fo)#回调种子用户的关注列表14.yieldRequest(self.user_url.format(user=self.start_user,include=self.user_include),callback=self.parse_user)#回调种子用户的个人信息15.16.defparse_user(self,response):17.result=json.loads(response.text)18.print(result)19.item=ZhihuxjjItem()20.item['user_name']=result['name']21.item['sex']=result['gender']#gender为1是男,0是女,-1是未设置22.item['user_sign']=result['headline']23.item['user_avatar']=result['avatar_url_template'].format(size='xl')24.item['user_url']='['url_token']25.iflen(result['locations']):26.item['user_add']=result['locations'][0]['name']27.else:28.item['user_add']=''29.yielditem30.31.defparse_fo(self,response):32.results=json.loads(response.text)33.forresultinresults['data']:北大青鸟华美官网:(self.user_url.format(user=result['url_token'],include=self.user_include),callback=self.parse_user)35.yieldRequest(self.followees_url.format(user=result['url_token'],offset=0),callback=self.parse_fo)#对关注者的关注者进行遍历,爬取深度depth+=136.ifresults['paging']['is_end']isFalse:#关注列表页是否为尾页37.next_url=results['paging']['next'].replace('http','https')38.yieldRequest(next_url,callback=self.parse_fo)39.else:40.pass这里需要划重点的是yield的用法,以及item['name'],将爬取结果赋值给item,就是告诉系统,这是我们要选的菜…啊呸…要爬的目标数