您的位置:首页 > 编程语言 > Python开发

python简单爬虫案例(二十一)

2018-03-25 16:16 651 查看
python简单爬虫案例:
这个案例主要是想爬取熊猫TV主播的排行。
1.首先是要明确爬取目标: https://www.panda.tv/cate/lol
2.分析网页数据所在位置。
3.模拟http请求,向服务器发送这个请求,获取到服务器返回的HTML。
4.用正则表达式或取数据。

首先还是先要试着访问以下网络,或者里面的HTML:
from urllib import request

class spider():
url = 'https://www.panda.tv/cate/lol'
def _fecth_content_(self):
r = request.urlopen(spider.url)
htmls = r.read()
pass
def go(self):
self._fecth_content_()

sp = spider()
sp.go()
直接使用的就是urllib里面的request访问网络,读取html的内容。
 通过断点调试,发现htmls里面有很多的数字:



其实这些东西是字节码,用的是pycharm。
所以得转码,国内网站多用utf-8或gbk,其实看html的开头编码也可以知道的。
htmls = str(htmls , encoding='utf-8')
拿到编码之后就要进行一个转码了。



再调试就出来数据了。

接下来就是分析爬下来的数据了:
首先要找到爬取数据的唯一性。





可以看到显示用户名字的就是nickname了。



其实如果是直接选择nickname和number的话,这样是很难对应起来的
而看到上面video-info就包括了nickname和number,所以可以先拿到video-info的内容,然后再找里面的对应数据。



其实爬虫就是把信息精确化,一开始拿到是一个很模糊的数据,慢慢用正则进行标准化去除干扰数据。

pattern = '<div class="video-info">([\s\S]*?)</div>'
name_pattern = '</i>([\s\S]*?)</span>'
number_pattern = '<span class="video-number">([\s\S]*?)</span>'
这个正则表达式加上?。其实就是把贪婪原则转变为非贪婪原则,因为</div>不是独有的,如果不加?取消非贪婪,那么后面的</div>也会被匹配到的,他会选取最长的来匹配。
先是把需要的内容都截取出来。()就是把内容变成一个组,这样前后就不会包括了。
def __analysis(self , htmls):
root_html = re.findall(spider.pattern , htmls)
anchors = []
for html in root_html:
name = re.findall(spider.name_pattern , html)
number = re.findall(spider.number_pattern , html)
name_number = {'name' : name , 'number' : number}
anchors.append(name_number)
pass
return anchors
pass
拿到名字和人数放到列表里面。
但是还有一个,名字是有很多空格的,并没有对空格进行处理:
def __refine(self , anchors):
l = lambda anchors : {'name' : anchors['name'][0].strip() ,
'number' : anchors['number'][0]
}
return map(l , anchors)
pass
使用strip函数去除空格。



这样就可以了。

之后就是排序了:
排序要使用sorted函数:
def __sort(self ,anchors):
anchors = sorted(anchors , key=self.__sort_seed , reverse=True)
return anchors
pass
def __sort_seed(self , anchor):
return anchor['number']
pass


可以看到,效果并不好。
首先就__sort_seed函数返回的是一个字符串,字符串是会把第一个字符进行排序的,所以应该要返回一个数字。

def __sort_seed(self , anchor):
r = re.findall('\d*' , anchor['number'])
number = float(r[0])
if '万' in anchor['number']:
number *= 10000
return number
pass这是修改之后的seed函数
这样返回结果就正确了:



到这里就完成了。

整个代码:
from urllib import request
import re
class spider():
url = 'https://www.panda.tv/cate/lol'
pattern = '<div class="video-info">([\s\S]*?)</div>'
name_pattern = '</i>([\s\S]*?)</span>'
number_pattern = '<span class="video-number">([\s\S]*?)</span>'
def __fecth_content_(self):
r = request.urlopen(spider.url)
htmls = r.read()
htmls = str(htmls , encoding='utf-8')
return htmls
pass
def __analysis(self , htmls):
root_html = re.findall(spider.pattern , htmls)
anchors = []
for html in root_html:
name = re.findall(spider.name_pattern , html)
number = re.findall(spider.number_pattern , html)
name_number = {'name' : name , 'number' : number}
anchors.append(name_number)
pass
return anchors
pass
def __refine(self , anchors):
l = lambda anchors : {'name' : anchors['name'][0].strip() ,
'number' : anchors['number'][0]
}
return map(l , anchors)
pass
def __sort(self ,anchors):
anchors = sorted(anchors , key=self.__sort_seed , reverse=True)
return anchors
pass
def __sort_seed(self , anchor):
r = re.findall('\d*' , anchor['number'])
number = float(r[0])
if '万' in anchor['number']:
number *= 10000
return number
pass
def __show(self , anchors):
for anchor in anchors:
print(anchor['name'] + '----------' + anchor['number'])
pass
def go(self):
htmls = self.__fecth_content_()
anchors = self.__analysis(htmls)
anchors = self.__refine(anchors)
anchors = self.__sort(anchors )
self.__show(list(anchors))
sp = spider()
sp.go()可以看到这个代码除了go函数,其他的函数就是一个私有函数。go其实就是一个入口函数,使用这个入口函数来调用其他的私有函数。其实go函数就是和java的main函数就是差不多的,都是属于一个入口。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: