Python初学者之网络爬虫(二)
声明:本文内容和涉及到的代码仅限于个人学习,任何人不得作为商业用途。转载请附上此文章地址
本篇文章Python初学者之网络爬虫的继续,最新代码已提交到https://github.com/octans/PythonPractice
1. 上篇回顾
上篇文章Python初学者之网络爬虫中我从花椒的热门推荐页面入手,进而获取到主播个人信息和对应的直播历史视频。
首先看一下上一篇文章中对huajiao.com的主播和视频的爬取成果:
# getUserCount # getLiveCount
到目前为止我新做了如下事情:
- 对MySql的读写操作进行了封装
- 编码风格遵从PEP8
- 爬取沃米优选网(http://video.51wom.com/)的主播信息
- 爬取一下网(http://www.yixia.com/)的主播信息和视频信息
其中对MySql的封装代码单独放到了文件mysql.py下,做为一个module使用,这个module虽然简单,但已经实现了select,insert,delete等操作,对MySql封装感兴趣的同学可以参考, 但请不要用于生产环境。推荐去使用和阅读数据库类peewee。
接下来将继续讲述我在数据抓取上的开发经历。
2. 爬取的数据源和逻辑
最终目标:收集到各大直播平台的主播信息和历史播放记录,进而对数据进行聚合分析。
当前已完成:对花椒网的数据收集。
沃米优选网(http://video.51wom.com/)是一个网红数据聚合的网站,它收集了各个直播平台(花椒,熊猫,秒拍,斗鱼,映客,一直播,美拍)的热门主播信息。所以我希望能从它这里获取到各个平台的热门主播信息,之后拿着主播id去对应的直播平台去爬取更详细的信息。
3. 爬取沃米优选网的主播列表页
列表页http://video.51wom.com/截图如下:
初看这是一个列表页,并且底部有分页链接,点击分页时触发表单提交
3.1 分析结论和构思程序逻辑
当点击底部分页时,使用chrom开发者工具,看到有XHR请求如下截图:
从截图和一些测试可以分析出:
- a) 要请求第二页以后的数据,需要将相应的cookie和csrf数据提交给网站;
- b) 提交的方式是POST的”multipart/form-data”;
- c) 提交的参数有_csrf, stage-name, platform, industry等;
- d) 请求的返回结果是一个表格列表的html代码;
对于cookie容易拿到,但_csrf如何获取呢?
查看页面源码,发现网站在生成列表页时已经将csrf的值写入了表单;同一个csrf值在后续请求中可以多次使用
<input type="hidden" name="_csrf" value="aWF6ZGMzclc9EAwRK3Y4LhobNQo6eEAdWwA0IFd1ByUDNTgwClUEZw==">
由以上分析,程序的逻辑应该这样,
- a) 先请求主播列表的首页,获取到csrf值和cookie
- b) 将csrf和cookie值保存,用于下次请求
- c) 请求主播列表的第二页,第三页等
- d) 将获取到的表格列表的html代码使用BeautifulSoup进行解析,遍历每个行,行里的每个列
- e) 将获取到的数据写入mysql
3.2 python编码获取沃米优选网的主播信息
a) 构造基础类class Website, 之后为每个网站建立一个class,继承Website
- 有些请求返回的是html代码,类里设置好html解析器;
- 有些请求返回的是json串,基类里设置好json的解析器;
- 请求每个网站时,需要设置不同的header,将header放在基类;
- 对post的Content-Type:multipart/form-data方式进行函数封装;
- 对post的Content-Type: application/x-www-form-urlencoded方式分别进行函数封装;
- 这里面尽量把各种不同的请求方式写成函数,而不使用type参数的形式,便于子类清晰的调用;
注意以下代码为了节省篇幅,不是完整代码,也非PEP8代码规范
class Website:
### 使用requests.session()能够自动处理cookies
session = requests.session() ### 设置html解析器
htmlParser = BeautifulSoup ### 设置json解析器
jsonParser = json ### 设置headers
headers = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/'
'54.0.2840.98 Safari/537.36'
}
### 直接发起get请求
def get(self, url, params=None):
if params is None:
params = {}
return self.session.get(url, params=params, headers=self.headers) ### 发起get请求并返回解析后的html对象
def get_html(self, url, params=None):
r = self.get(url, params)
return self.htmlParser(r.text, 'html.parser') ### 发起get请求并返回解析后的json对象
def get_json(self, url, params=None):
r = self.get(url, params)
return self.jsonParser.loads(r.text) ### 发起post请求,以Content-Type:multipart/form-data方式
def post_multi_part(self, url, params):
kwargs = dict()
for (k, v) in params.items():
kwargs.setdefault(k, (None, v))
r = self.session.post(url, files=kwargs, headers=self.headers)
return self.htmlParser(r.text, "html.parser")
b) 构造class WoMiYouXuan, 封装对网站沃米优选的请求
- 方法first_kiss()用于第一次请求网站,获取到csrf值由属性self.csrf保存;
- first_kiss()另一个作用是获取到cookie,虽然没有显示处理,因为requests.session()帮我们处理了,自动获取自动提交;
- 注意在一个实例里,只需调用一次first_kiss()即可,之后就可以多次调用其他的页面请求函数了;
- csrf和cookie是由关联的,网站会校验,都要提交;
- 方法parse_actor_list_page()是具体分析主播的列表html代码,这是一个细致活;
- 方法spider_actors是骨架函数,循环访问每个分页数据并将结果写入mysql;
class WoMiYouXuan(Website):
### 发起post请求时需要将csrf发给网站
csrf = ''
def __init__(self):
self.first_kiss() ### 首次访问该网站获取到csrf值并保存到self.csrf, 供其他post请求直接使用
def first_kiss(self):
url = 'http://video.51wom.com/'
html = self.get_html(url)
self.csrf = html.find('meta', {'name': 'csrf-token'}).attrs['content'] ### 从主播列表页获取主播信息
def parse_actor_list_page(self, page=1):
### 构造参数->发起post请求
url = 'http://video.51wom.com/media/' + str(page) + '.html'
keys = ('_csrf', 'stage-name', 'platform', ' industry', 'price', 'follower_num', 'follower_area',
'page', 'is_video_platform', 'sort_by_price', 'type_by_price')
params = dict()
for key in keys:
params.setdefault(key, '')
params['_csrf'] = self.csrf
params['page'] = str(page)
html = self.post_multi_part(url, params) ### 解析主播列表
trs = html.find('div', {'id': 'table-list'}).table.findAll('tr')
trs.pop(0) # 去除标题行
actor_list = list()
for tr in trs:
### 后面太多了,有兴趣的同学去看源码吧 ### 骨架函数,循环访问每个分页数据并将结果写入mysql
def spider_actors(self):
page = 1
tbl_actor = WMYXActor()
while True:
ret = self.parse_actor_list_page(page)
for actor in ret['items']:
actor['price_dict'] = json.dumps(actor['price_dict'])
tbl_actor.insert(actor, replace=True)
if ret['items_count'] * ret['page'] < ret['total']:
page += 1
else:
break
方法parse_actor_list_page()具体分析主播列表的html代码,这是一个细致活;感受一下代码截图
3.3 知识点总结
a) 表单提交的POST方式
通常只提交一些kv数据时,使用application/x-www-form-urlencoded方式;
通常上传文件时,使用multipart/form-data方式,但此种方式也是可以提交kv类数据的,比如上面的获取主播列表数据时就是使用此方式。
b) Python的网络请求库Requests
这个库太好用了!并且能够对cookie自动处理,比如我在基类Website中的使用方式; 并且使用它构造multipart/form-data方式的post请求也很方便,比如方法Website::post_multi_part()
c) Python中使用正则匹配字符串中的整数,如下代码:
avg_watched = tds[6].get_text(strip=True) # 平均观看人数
mode = re.compile(r'\d+')
tmp = mode.findall(avg_watched)
d) 使用try, except机制来实现类似php里的isset(),如下代码:
# 判断是否有逗号,比如8,189
try:
index = string.index(',')
string = string.replace(',', '')
except ValueError:
string = string
e) 一定要注意python中的’1’和1是不一样的,需要你自己来做字符串和数字的类型转换
4. 爬取秒拍网的主播和视频信息
在沃米优选网拿到了各个直播平台的主播id, 先实现对一下网(http://www.yixia.com/)的抓取,获取对应的主播和视频信息。
一下网的个人主页地址为http://www.yixia.com/u/uid, 这个uid就是主播id, 如下截图:
4.1 分析结论和构思程序逻辑
- a) 在主播个人主页能够拿到主播的个人信息,如头像,昵称,粉丝数等,还能拿到主播的视频列表;
- b) 视频列表的加载方式是瀑布流方式,意味着走的是ajax接口;
- c) 视频列表接口返回的数据是html代码,仍然需要用BeautifulSoup解析;
- d) 请求视频列表接口时需要提交suid参数,这个参数值需要用uid在主播个人页获取;
4.2 python编码一下网的主播信息和视频列表
- 构造class YiXia(Website),
- 方法parse_user_page()拿着uid去获取主播个人信息;
- 方法get_video_list()按分页获取视频列表数据
class YiXia(Website):
### 访问主播页面,也是视频列表页,从该页面获取到suid和主播个人信息
def parse_user_page(self, uid):
print(self.__class__.__name__ + ':parse_user_page, uid=' + uid)
user = dict()
user['uid'] = uid
url = 'http://www.yixia.com/u/' + uid
bs = self.get_html(url) div = bs.find('div', {'class': 'box1'})
user['nickname'] = div.h1.a.get_text(strip=True) # 昵称 stat = div.ol.get_text(strip=True)
stat = re.split('关注\||粉丝', stat)
user['follow'] = stat[0].strip() # 关注数
user['followed'] = stat[1].strip() # 粉丝数
### ------这里省略很多代码---- return user ### AJAX请求视频列表
def get_video_list(self, suid, page=1):
url = 'http://www.yixia.com/gu/u'
payload = {
'page': page,
'suid': suid,
'fen_type': 'channel'
}
json_obj = self.get_json(url, params=payload)
msg = json_obj['msg']
msg = BeautifulSoup(msg, 'html.parser') ### 解析视频标题
titles = list()
ps = msg.findAll('p')
for p in ps:
titles.append(p.get_text(strip=True)) # 视频标题 ### 解析视频赞和评论数
stats = list()
divs = msg.findAll('div', {'class': 'list clearfix'})
for div in divs:
tmp = div.ol.get_text(strip=True)
tmp = re.split('赞|\|评论', tmp)
stats.append(tmp) ### 解析视频其他数据
videos = list()
divs = msg.findAll('div', {'class': 'D_video'})
for (k, div) in enumerate(divs):
video = dict()
video['scid'] = div.attrs['data-scid'] ### ------这里省略很多代码------ return videos ### 骨架函数,获取每个视频的每个分页数据
def spider_videos(self, suid, video_count):
page = 1
current = 0
tbl_video = YiXiaVideo()
while current < int(video_count):
print('spider_videos: suid=' + suid + ', page=' + str(page))
videos = self.get_video_list(suid, page)
for video in videos:
tbl_video.insert(video, replace=True)
current += len(videos)
page += 1
return True
4.3 知识点总结
大部分还是3.3里的知识点,这里重点注意字符串和整形,浮点型数字的转换。比如粉丝数’2.3万’是一个字符串,需要转成浮点数2.3或者整数23000;再比如’8,189’需要转成8189.
5. 程序结果
以下截图为采集到的一下网视频数据:
6. 知识点参考
这里列出我记录下来的参考链接:
- 解析json: JSON encoder and decoder
- 解析html: BeautifulSoup
- 构造http请求:Requests
- 文件操作:Reading and Writing Files
- 数据库的ORM库: peewee
- 对字符串的操作:Python 字符串操作
- 对list的操作:More on Lists|Python 列表(List)操作方法详解
- 对dict的操作:Dictionaries|Python中dict详解
- 对True和Flase的使用:Python的Boolean操作
- POST提交方式:四种常见的 POST 提交数据方式
- Python编码风格:PEP8

Python初学者之网络爬虫(二)的更多相关文章
- Python初学者之网络爬虫
声明:本文内容和涉及到的代码仅限于个人学习,任何人不得作为商业用途. 本文将介绍我最近在学习Python过程中写的一个爬虫程序,将力争做到不需要有任何Python基础的程序员都能读懂.读者也可以先跳到 ...
- [Python学习] 简单网络爬虫抓取博客文章及思想介绍
前面一直强调Python运用到网络爬虫方面很有效,这篇文章也是结合学习的Python视频知识及我研究生数据挖掘方向的知识.从而简介下Python是怎样爬去网络数据的,文章知识很easy ...
- Python 利用Python编写简单网络爬虫实例3
利用Python编写简单网络爬虫实例3 by:授客 QQ:1033553122 实验环境 python版本:3.3.5(2.7下报错 实验目的 获取目标网站“http://bbs.51testing. ...
- Python 利用Python编写简单网络爬虫实例2
利用Python编写简单网络爬虫实例2 by:授客 QQ:1033553122 实验环境 python版本:3.3.5(2.7下报错 实验目的 获取目标网站“http://www.51testing. ...
- Python 基础教程 —— 网络爬虫入门篇
前言 Python 是一种解释型.面向对象.动态数据类型的高级程序设计语言,它由 Guido van Rossum 于 1989 年底发明,第一个公开发行版发行于 1991 年.自面世以后,Pytho ...
- 智普教育Python培训之Python开发视频教程网络爬虫实战项目
网络爬虫项目实训:看我如何下载韩寒博客文章Python视频 01.mp4 网络爬虫项目实训:看我如何下载韩寒博客文章Python视频 02.mp4 网络爬虫项目实训:看我如何下载韩寒博客文章Pytho ...
- 从零开始学Python 三(网络爬虫)
本章由网络爬虫的编写来学习python.首先写几行代码抓取百度首页,提提精神,代码如下: import urllib.request file=urllib.request.urlopen(" ...
- Python中的网络爬虫怎么用?
爬虫概述 (约2016年)网络爬虫个人使用和科研范畴基本不存在问题,但商业盈利范畴就要看对方了. 通过网站的Robots协议(爬虫协议)可以知道可以和不可以抓取的内容,其中User-Agent: 为允 ...
- 【Python开发】【神经网络与深度学习】如何利用Python写简单网络爬虫
平时没事喜欢看看freebuf的文章,今天在看文章的时候,无线网总是时断时续,于是自己心血来潮就动手写了这个网络爬虫,将页面保存下来方便查看 先分析网站内容,红色部分即是网站文章内容div,可以看 ...
随机推荐
- 设计爬虫Hawk背后的故事
本文写于圣诞节北京下午慵懒的午后.本文偏技术向,不过应该大部分人能看懂. 五年之痒 2016年,能记入个人年终总结的事情没几件,其中一个便是开源了Hawk.我花不少时间优化和推广它,得到的评价还算比较 ...
- .NET 基础 一步步 一幕幕[面向对象之方法、方法的重载、方法的重写、方法的递归]
方法.方法的重载.方法的重写.方法的递归 方法: 将一堆代码进行重用的一种机制. 语法: [访问修饰符] 返回类型 <方法名>(参数列表){ 方法主体: } 返回值类型:如果不需要写返回值 ...
- ASP.NET Core应用的错误处理[1]:三种呈现错误页面的方式
由于ASP.NET Core应用是一个同时处理多个请求的服务器应用,所以在处理某个请求过程中抛出的异常并不会导致整个应用的终止.出于安全方面的考量,为了避免敏感信息的外泄,客户端在默认的情况下并不会得 ...
- .net windows Kafka 安装与使用入门(入门笔记)
完整解决方案请参考: Setting Up and Running Apache Kafka on Windows OS 在环境搭建过程中遇到两个问题,在这里先列出来,以方便查询: 1. \Jav ...
- B样条基函数的定义和性质
定义:令U={u0,u1,…,um}是一个单调不减的实数序列,即ui≤ui+1,i=0,1,…,m-1.其中,ui称为节点,U称为节点矢量,用Ni,p(u)表示第i个p次(p+1阶)B样条基函数,其定 ...
- 免费高效实用的.NET操作Excel组件NPOI(.NET组件介绍之六)
很多的软件项目几乎都包含着对文档的操作,前面已经介绍过两款操作文档的组件,现在介绍一款文档操作的组件NPOI. NPOI可以生成没有安装在您的服务器上的Microsoft Office套件的Excel ...
- CSharpGL(33)使用uniform块来优化对uniform变量的读写
CSharpGL(33)使用uniform块来优化对uniform变量的读写 +BIT祝威+悄悄在此留下版了个权的信息说: Uniform块 如果shader程序变得比较复杂,那么其中用到的unifo ...
- 3种web会话管理的方式
http是无状态的,一次请求结束,连接断开,下次服务器再收到请求,它就不知道这个请求是哪个用户发过来的.当然它知道是哪个客户端地址发过来的,但是对于我们的应用来说,我们是靠用户来管理,而不是靠客户端. ...
- CSS入门常见的问题
写在前面:本文简单介绍一下css的三大特性:层叠性.继承性.优先级.以及margin,padding,浮动,定位几个知识点.限于水平,不深入探讨,仅作为学习总结. 1,三特性 1)层叠性:同标签同权重 ...
- BAT“搅局”B2B市场,CIO们准备好了吗?
"CIO必须灵活构建其所在企业的IT系统,深入业务,以应对日新月异的数字化业务环境." BAT军团"搅局"B2B市场,CIO们准备好了吗? 庞大的企业级市场 ...