python爬虫学习笔记

397次阅读
没有评论
python爬虫学习笔记

在使用命令行创建scrapy项目后,会发现在spider.py文件内会生成这样的代码:

name = 'quotes' allowed_domains = ['quotes.toscrape.com'] start_urls = ['http://quotes.toscrape.com/']

其中比较好理解的是name,这个字段代表爬虫项目名称,在命令行创建时已经指定,allowed_domains代表允许爬取的域名,这两个字段均在创建时已经设置好,不需要更改,但比较特殊的是start_url这个字段,它也是一个列表形式,官方文件的解释为包含spider在启动时爬取的url列表,用于定义初始请求。这样就可以类比如果不使用scrapy框架,url应该如何定义;
例如爬取豆瓣读书时发现首页url为"https://book.douban.com/top250?start=0",
以后每翻页一次start字段值递增25,这样就可以很容易用一个循环做到url的构建,再比如如果爬取今日头条图片,分析Ajax后首页url为“https://www.toutiao.com/search_content/?offset=0&format=json&keyword=街拍&autoload=true&count=20&cur_tab=1&from=search_tab&pd=synthesis”,以后每页更改其中offset参数递增20,则可以利用urlencode()方法构建url。
其实scrapy的start_url构建方法与普通爬虫的构建本质上没有任何区别,只是因为在框架的调度使其实现更加容易。
下面以http://images.so.com网站为例:
创建好项目文件后,spider.py内的代码如下:

class ImagesSpider(Spider): name = 'images' allowed_domains = ['images.so.com'] start_urls = ['http://images.so.com/']

def prase(self): pass

如果我们不做任何其他处理,则爬虫启动只会爬取"http://images.so.com/"上的内容。
因为这是一个列表形式,笨一点的方法就是把所有要爬取的url添加到列表中,然后遍历就可以了:

start_urls = [ 'http://images.so.com/z?ch=beauty', 'http://images.so.com/z?ch=wallpaper']

for url in start_urls: yield scrapy.Request(url=url, callback=self.parse)

这样当然没错,而且还很好理解,但未免显得太实在了。既然要返回一组列表,自然而然就可以用到以前的构建方法,构建代码如下:

def start_requests(self): data={'ch':'photography','listtype':'new'} base_url='https://image.so.com/zj?' for page in range(1,self.settings.get('MAX_PAGE')+1): data['sn']=page*30 params=urlencode(data) url=base_url+params yield Request(url=url,callback=self.parse)

这里的url是分析Ajax得到的,可以看出构建方法没有什么特别之处,这个方法返回的Request请求,而回调函数就是我们解析html的方法,爬虫运行时,不断的将请求生成并被parse()方法调用解析,parse()方法代码如下:

def parse(self, response): result=json.load(response.text) for image in result.get('list'): item=Images360Item() item['id']=image.get('imageid') item['url']=image.get('qhimg_url') item['title']=image.get('group_title') item['thumb']=image.get('qhimg_thumb_url') yield item

当涉及到不止一层关系的爬虫,例如微博的爬取,爬取了微博首页后,还要爬取它的关注,粉丝,微博列表的情况下,就相对复杂的多了。但其实本质是一样的,只是下一层的start_url的构建不是在start_request()方法中,而是在第一层罗辑的解析方法中生成,伪代码如下,以微博为例:

class WeibocSpider(Spider): name = 'weiboc' allowed_domains = ['m.weibo.cn'] user_url='' follow_url='' fan_url='' weibo_url='' start_user=['3217179555'] def start_requests(self): for uid in self.start_user: yield Request(self.user_url.format(id=uid),callback=self.parse_user)

def parse_user(self,response): self.logger.debug(response) result=json.loads(response.text) if result.get('data').get('userInfo'): user_Info=result.get('data').get('userInfo') user_item=UserItem() field_map={} for field ,attr in field_map.items(): user_item[field]=user_Info.get['attr']#返回用户信息

#关注 uid=user_Info.get('id') #构造下一页链接,并返回Request yield Request(self.follow_url.format(uid=uid,page=1),callback=self.parse_follows,meta={'page':1,'uid':uid})

#fans yield Request(self.fan_url.format(uid=uid,page=1),callback=self.parse_fans,meta={'page':1,'uid':uid})

#weibo yeild Request(self.weibo_url.format(uid=uid,page=1),callback=self.parse_weibos,meta={'page':1,'uid':uid})

def parse_follows(self,response): """ 解析用户关注 :param response: Response对象 :return: """ result=json.loads(response.text) if result.get('ok') and result.get('data').get('cards') and len(result.get('data').get('cards')) and result.get('data').get('cards')[1].get('card_group'): #解析关注列表每个用户信息并发起新的解析请求 follows=result.get('data').get('cards')[1].get('card_group') for folow in follows: if follow.get('user'): uid=follow.get('user').get('id') yield Request(self.user_url.format(uid=uid)callback=self.parse_user())

#关注列表 uid=response.meta.get('uid') user_relation_item=UserRelationItem() follows=[{'id':follow.get('user').get('id'),'name':follow.get('user').get('screen_name')}for follow in follows] user_relation_item['id']=uid user_relation_item['follows']=follows user_relation_item['fans']=[] yield user_relation_item

#提取下一页的关注 page=response.meta.get('page')+1 yield Request(self.follow_url.format(uid=uid,page=page),callback=self.parse_follows,meta={'page':page.'uid':uid})

这里首先通过start_request()方法生成要爬取的微博首页请求,在parse_users()方法解析得到用户信息后,再生成下一层罗辑需要的请求列表,这样就可以实现一层层不断的爬取,貌似用到了深度优先的概念。
ps:GitHub地址:https://github.com/linl12138/image

神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试

相关文章:

版权声明:Python教程2022-10-25发表,共计4620字。
新手QQ群:570568346,欢迎进群讨论 Python51学习