Python的原生爬虫案例

该文介绍了如何不使用爬虫框架,通过Python实现数据爬取。内容包括分析网站结构,使用正则表达式抓取HTML中的主播姓名和人气数据,以及处理反爬机制,如自动登录和代理IP。文章还强调了代码结构和书写规范,以及如何进行数据排序和展示。
摘要由CSDN通过智能技术生成

完整的爬虫:

反扒机制,自动登录,代理IP等等

复制

示例爬虫:

简单的数据抓取,简单的数据处理

复制

目的:

不使用爬虫框架完成数据爬取
巩固知识、合理编程、内部原理

复制

示例内容:

内容:
    爬取直播网站
确定工作:
    确定爬取数据:某个分类下各主播人气的数据
    确定实现结果:将人气进行排序
准备:
    分析网站结构
    寻找包含爬取信息的页面
    F12检查网页,定位信息(主播姓名,人气数据)
原理:
    对html文件进行文本分析并从中提取信息
使用技术
    正则表达式
具体步骤:
    模拟HTTP请求,向服务器发送请求,获取到服务器返回的HTML
    用正则表达式处理网页文本,过滤出有用数据
    找到相关常量标签,作为正则的定位边界
    定位标签:
        尽量选择具有唯一标识的标识的标签
        尽量选择与目标数据相近的标签
        尽量选择将所有目标数据都包含的标签(闭合的标签),比如包含姓名+人气的标签
        上述即尽量选父标签,不选兄弟标签,为了易于构造正则提取内容
注意:
    构造正则不是难点,难点是应对反爬虫的措施

整体书写规范
    每行代码不要过长
    推荐书写一个入口程序
    推荐在入口中平行的调用逻辑代码
    每个方法中代码尽量少
    注意块注释和行级注释的书写格式


代码结构:

复制

'''
类注释
'''
class spider():
	#抓取页面内容(行注释)
	def __fetch_content(self):
		'''
		方法注释
		'''
		pass
	#数据抽取
	def __analysis(self, htmls):
		pass
	#数据精炼
	def __refine(self, pairs):
		pass
	#排序
	def __sort(self, pairs):
		pass
	#排序的算子
	def __seed(self, pairs):
		pass
	#数据展现
	def __show(self, pairs):
		pass
	
	#函数入口
	def go(self):
调用
s = spider()
s.go()  	
```			
	书写代码:
		抓取页面:
			url = 'http://www.huya.com/g/lol'
		分析原网页:

复制

<li class="game-live-item" gid="1">
    <a href="http://www.huya.com/yanmie" class="video-info new-clickstat" target="_blank" report='{"eid":"click/position","position":"lol/0/1/5","game_id":"1","ayyuid":"380335691"}'>
        <img class="pic" data-original="//screenshot.msstatic.com/yysnapshot/1711a622dc4d670fe32de2018f78a2d030fcde37cfe8?imageview/4/0/w/338/h/190/blur/1" src="//a.msstatic.com/huya/main/assets/img/default/338x190.jpg" onerror="this.onerror=null; this.src='//a.msstatic.com/huya/main/assets/img/default/338x190.jpg';" alt="最强赵信折翼的直播" title="最强赵信折翼的直播">
                <div class="item-mask"></div>
        <i class="btn-link__hover_i"></i>
        <em class="tag tag-blue">蓝光</em>    </a>
    <a href="http://www.huya.com/yanmie" class="title new-clickstat" report='{"eid":"click/position","position":"lol/0/1/5","game_id":"1","ayyuid":"380335691"}' title="可以用赵信上王者第一的男人" target="_blank">可以用赵信上王者第一的男人</a>
    <span class="txt">
        <span class="avatar fl">
            <img data-original="//huyaimg.msstatic.com/avatar/1081/63/c83bdc0701b64646c86065e273fd05_180_135.jpg" src="//a.msstatic.com/huya/main/assets/img/default/84x84.jpg" onerror="this.onerror=null; this.src='//a.msstatic.com/huya/main/assets/img/default/84x84.jpg';" alt="最强赵信折翼" title="最强赵信折翼">
            <i class="nick" title="最强赵信折翼">最强赵信折翼</i>
        </span>
                <span class="num"><i class="num-icon"></i><i class="js-num">1.5万</i></span>
    </span>
</li>

复制

<span class="txt">
    <span class="avatar fl">
        <img data-original="//huyaimg.msstatic.com/avatar/1081/63/c83bdc0701b64646c86065e273fd05_180_135.jpg" src="//a.msstatic.com/huya/main/assets/img/default/84x84.jpg" onerror="this.onerror=null; this.src='//a.msstatic.com/huya/main/assets/img/default/84x84.jpg';" alt="最强赵信折翼" title="最强赵信折翼">
        <i class="nick" title="最强赵信折翼">最强赵信折翼</i>
    </span>
            <span class="num"><i class="num-icon"></i><i class="js-num">1.5万</i></span>
</span>

复制

目标数据:
	最强赵信折翼,1.5万
构造正则表达式:
	选出上面的最小公约子集:	
		root_pattern = '<span class="txt">([\s\S]*?)\r\n</li>' 
		注意:
			要加问号,声明是非贪婪的匹配
	
	然后选出,姓名:	
		name_pattern = '<i class="nick" title="([\s\S]*?)">'
	然后选出,人气:
		num_pattern = '<i class="js-num">([\s\S]*?)</i>'
	
	注意:
		上述正则的边界并不一定是完整的html标签,因为使用正则即对字符进行匹配,所以可以随意拆分。
		
几个重要功能:
	获取页面内容:
		from urllib import request
		tmp = request.urlopen(spider.url)
		htmls = tmp.read() 
		注意:此处的结果是字节码:bytes
		必须要进行转化:bytes->str
		htmls = str(htmls,encoding='utf-8')
		 
		注意:不推荐打印出页面内容,会出现解码问题,可以加断点调试
 
	循环:
		此处的循环需要获取到下标,而直接for i in list,获取不到下标
		此时应该使用for index in range(0,len(list))这种形式
		代码:
			for rank in range(0, len(pairs)):
				print('第',rank,'名:',pairs[rank]['name'],':',pairs[rank]['number'])
	排序:
		此处使用内置函数sorted(iterable, cmp=None, key=None, reverse=False)
		注意:
			key = 函数名,此函数应该返回排序的比较值
			cmp = 函数名,此函数可以重写排序规则
			reverse=False,从小到大正序排列
		代码:
			sorted(pairs,key = seed,reverse = True)
			def seed(self, pairs):
				tmp = pairs['number'].replace('万','')
				if('万' in pairs['number']):
					tmp = float(tmp) * 10000
				return int(tmp)
完整的爬虫代码:

复制

from urllib import request import re

class spider():

url = 'http://www.huya.com/g/lol'
root_pattern = '<span class="txt">([\s\S]*?)\r\n</li>' #父级目录匹配
# 使用概括字符集 [\d] [\w]  [\s]  [.]
#注意:要加问号,声明是非贪婪的匹配
name_pattern = '<i class="nick" title="([\s\S]*?)">'
num_pattern = '<i class="js-num">([\s\S]*?)</i>'

def __fetch_content(self):  #加__的函数:私有方法
    tmp = request.urlopen(spider.url)
    htmls = tmp.read() #此处的结果是字节码:bytes
    # bytes->str
    htmls = str(htmls,encoding='utf-8')
    a = 1#如果不添加这一句,htmls赋值发生在最后一句
    #那么断点停止时会得不到htmls的值,这时要人为多余的添加一条语句并将断点放到这里即可
    #print(htmls)不推荐打印,会出现解码问题
    return htmls

def __sort(self, pairs):
    #def sorted(iterable, cmp=None, key=None, reverse=False)
    #注意要指定key值
    return sorted(pairs,key=self.__seed,reverse=True)

def __show(self, pairs):
    #for循环中需要拿到序号,直接使用range形式的for循环
    for rank in range(0, len(pairs)):
        print('第',rank,'名:',pairs[rank]['name'],':',pairs[rank]['number'])

def __seed(self, pairs):
    tmp = pairs['number'].replace('万','')
    if('万' in pairs['number']):
        tmp = float(tmp) * 10000
    return int(tmp)

def __refine(self, pairs):
    f = lambda p: { 
        'name':p['name'][0].strip(),
        'number':p['number'][0]
         }
    return map(f, pairs)

def __analysis(self, htmls):
    root_htm = re.findall(spider.root_pattern,htmls)
    pairs = []
    for item in root_htm:
        name = re.findall(spider.name_pattern,item)
        num = re.findall(spider.num_pattern,item)
        pair = {'name':name,'number':num}
        pairs.append(pair)
    return pairs

#设置入口函数,这是一个主方法,里面都是平级函数,推荐这种写法 
def go(self):   
    htmls = self.__fetch_content()      #抓取页面内容
    pairs = self.__analysis(htmls)      #抽取所需数据
    pairs = list(self.__refine(pairs))  #数据精炼
    pairs = self.__sort(pairs)          #数据排序
    self.__show(pairs)                  #数据显示,或后续处理(入库等)

复制

#实例化并调用入口函数 s = spider() s.go() ``` 注意事项: 如果需要调试,不推荐站桩print,推荐使用断点调试 调试方法: 启动应用程序 F5 单步执行F10 跳到下一个断点 F5 调到函数内部 F11

    例如在 html = tmp.read() 处打断点
    在当前断点处,悬停鼠标会显示变量值,也可以在vscode左侧的甲壳虫选项中查看变量的值


缺陷:
    虽然通过类进行了封装,但是其实最基础的封装
    但是,复用性差,抵御需求变化的能力太差,违反开闭原则

进阶:
    可以使用更加面向对象的设计来完成功能
    借助构造函数__init__来对类进行带参数的实例化:
    代码:
        class Spider():
            '''
            This is a class
            '''
            url = ''
            root_pattern = ''
            name_pattern = ''
            num_pattern = ''

            def __init__(self,url,root_pattern,name_pattern,num_pattern): 
                Spider.url = url
                Spider.root_pattern = root_pattern
                Spider.name_pattern = name_pattern
                Spider.num_pattern = num_pattern    

        s = Spider(
            'http://www.huya.com/g/4',
            '<span class="txt">([\s\S]*?)\r\n</li>',
            '<i class="nick" title="([\s\S]*?)">',
            '<i class="js-num">([\s\S]*?)</i>'
        )
        s.go()  
    类封装的意义:
        这样封装可以完成一个主播人气排序的爬虫类,参数有四个:
            爬取的直播网站;
            爬取的名称人气的父元素的正则
            爬取名称的正则
            爬取人气的正则

展望:
    爬虫模块或框架:
        BeautifulSoup模块
        Scrapy框架(多线程、分布式、较臃肿,看需求谨慎使用)
    反反爬虫技术:
        频繁爬取会使IP被封,需要使用定时器!切记!!
        寻找代理IP库,应对封IP
    整个流程的核心:    
        爬取的原始数据如何处理,精炼
        处理的结果如何存储,分析

最后免费分享给大家一份Python全套学习资料,包含视频、源码,课件,希望能帮到那些不满现状,想提升自己却又没有方向的朋友。 

关于Python技术储备

学好 Python 不论是就业还是做副业赚钱都不错,但要学会 Python 还是要有一个学习规划。最后大家分享一份全套的 Python 学习资料,给那些想学习 Python 的小伙伴们一点帮助!

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。在这里插入图片描述

二、Python必备开发工具

在这里插入图片描述

这份完整版的Python全套学习资料已经打包好,需要的小伙伴可以戳下方链接免费领取

三、Python视频合集

观看零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。 在这里插入图片描述在这里插入图片描述

四、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。 在这里插入图片描述

五、Python练习题

检查学习结果。 在这里插入图片描述

六、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。 在这里插入图片描述在这里插入图片描述

因篇幅有限,仅展示部分资料,需要的同学用vx扫描上方二维码即可获取‘

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值