当前位置:   article > 正文

爬取豆瓣TOP250

爬取豆瓣TOP250

1.准备工作

(1)安装python,并安装jupyter库,便于使用jupyter notebook编辑页面
(2)安装python,可能需要配置环境变量,win10配置环境变量时,直接加一条新的路径
(3)安装好jupyter后,进入时先用命令进入jupyter库所在目录,再直接输入jupyter notebook,便可直接进入jupyter的网络编辑页面
例如:
cd #进入jupyter库所在c盘
cd 目录 #进入jupyter库所在目录
再输入jupyter notebook
结果如下:
在这里插入图片描述
出现此界面后便会自动跳转到jupyter的网络编辑页面,如下:
在这里插入图片描述

2.开始爬取网页
(1)分析网页

分析URL链接:
第一页:https://movie.douban.com/top250 或 https://movie.douban.com/top250?start=0&filter=
第二页:https://movie.douban.com/top250?start=25&filter=
第三页:https://movie.douban.com/top250?start=50&filter=
第四页:https://movie.douban.com/top250?start=75&filter=
分析结果:从此可以看出,一至四页的URL链接是有规律 的,star=的后面,每个链接之间相差数字25
此时直接看第十页:
第十页URL为:

https://movie.douban.com /top250?start=225&filter=
  • 1

再看第一页的链接为:

https://movie.douban.com/top250?start=0&filter=
  • 1

仍然符合以上分析结果

(2)用for循环表示这个分析结果

结果如下:
在这里插入图片描述

(3)用page函数表示这10页的url链接

将函数改为:

for page in range(0, 226, 25):
url=‘https://movie.douban.com/top250?start=%s&filter=%page
  • 1
  • 2

将start=0改为start=%s,后面跟的%page表示将page函数中的数 值范围赋予给s,即可一次性构造出十个网页的链接
运行结果如下:
在这里插入图片描述
此时可随便点击一个链接进去,如点击start=75的链接进去,便进到top250 的第四页,而根据前面的分析,这个链接确实是第四页

3.正式爬取网页
(1)请求网页源代码,即html

实现这个目的,需要在python中安装request库,命令为pip install requests
以请求第一页为例:

test_url='https://movie.douban.com/top250?start=0&filter='
  • 1

此处的单引号也可以写成双引号,目的都是为了把括号内的内容变为字符串

(2)到top250上对代码进行审查

右击进入检查元素,点击网络(network),再点击所有(All)
对该网页进行刷新,下方会出现网页的组成元素,例如图片等
在这里插入图片描述

(3)请求网址以及请求方法

按上一步操作后,点击下图中的第一页的链接,再点击右边的消息头,可看到请求网址以及请求方法
在这里插入图片描述

(4)开始请求网页
test_url=’ https://movie.douban.com/top250?start=0&filter=’
requests.get(url= test_url)
  • 1
  • 2

requests表示库名,.get表示请求方法(网页中看到的是get),括号中的内容为第一页的链接
结果如下:
在这里插入图片描述
结果显示为418,浏览器识别出这个语句是爬虫程序,故拒绝返回值给我们
若改为

 test_url=’ https://movie.douban.com/top250?start=0&filter=’
 requests.get(url= test_url).text
  • 1
  • 2

同样返回不了值

(5)伪装浏览器

将程序伪装成正常的用户访问,躲过浏览器的识别,以便成功获取数据
首先,将代码审查中的用户代理复制过来,并将其够造成一个字典
用户代理为:

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0
  • 1
(6)代码表示
test_url=’ https://movie.douban.com/top250?start=0&filter=#设置浏览器代理,构造字典:
‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0
  • 1
  • 2
  • 3

#字典的构造方法:’a‘:‘b’
将字典放入括号内

requests.get(url= test_url, headers=headers).text
  • 1

(代码后加.text便会返回全部内容,不加的话只返回总行数)
结果如下:
在这里插入图片描述
还可将
requests.get(url= test_url, headers=headers).text的内容赋给一个值
例如:

reponse= requests.get(url= test_url, headers=headers).text
  • 1

此时再运行,没有显示,但是如果将它单独拿到下一行可以运行出内容,
运行结果如下:
在这里插入图片描述 运行出来的结果双击可隐藏
也可执行单独在一行print(reponse)来输出内容,输出的内容格式是排列好的

4信息的筛选

可供选择的分析工具有:
xpath(重点介绍)
re(正则)算法较复杂,xpath解决不了时考虑用这个,下面也会提到
BeautifulSoup,即BS4

(1) 安装lxml库

安装命令pip install lxml

(2)过滤
from lxml import etree
html_etree = etree.HTML (reponse)
print(html_etree )
  • 1
  • 2
  • 3
  • html_etree为自己命名,可随便写
  • HTML必须为大写
    运行结果如下:
    在这里插入图片描述
(3)从网页上(豆瓣TOP250)提取信息

(以提取‘风华绝代’四个字为例)
在这里插入图片描述其中,
html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li[2]/div/div[2]/div[2]/p[2]/span/text()')语句,html_etree为上述自己命名的过滤信息,.xpath表示使用该方法,
语句语法格式:

  • 过滤名.xpath('要提取信息的xpath路径')
    若要显示出文字来,则在路径后增加/text()
  • 过滤名.xpath('要提取信息的xpath路径/text()')显示结果如上图
    若要将文字外面的[]去掉,则在语句后加[0]
  • 过滤名.xpath('要提取信息的xpath路径/text()')[0]结果如下图所示
    在这里插入图片描述怎么寻找xpath路径?
    选中要提取的文字、右击检查元素、下方代码中显示出选中的文字后、在显示出的文字处右击复制,点击xpath即可。
(4)复制整个网页的xpath路径

打开网页,右击检查元素,找到每个电影模块对应的序列代码,如下图
在这里插入图片描述将图中右侧鼠标选中的位置的xpath路径复制下来为:

/html/body/div[3]/div[1]/div/div[1]/ol/li[1]
  • 1

依次,第二个的xpath路径为:

/html/body/div[3]/div[1]/div/div[1]/ol/li[2]
  • 1

第三个的xpath路径为:

/html/body/div[3]/div[1]/div/div[1]/ol/li[3]
  • 1

……
最后一个的xpath路径为:

/html/body/div[3]/div[1]/div/div[1]/ol/li[25]
  • 1

由此可发现,它们的xpath路径是有规律的,即最后一个[]中的数字从1开始,增加到25

  • 接下来用语句表示出
html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li[2]')
  • 1

将语句后的[数字]删除,便可表示所有的xpath路径

即html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li')
  • 1

此时运行结果为:
在这里插入图片描述下方共有25个返回值,li为自己写的赋值,可用len()函数查看返回值的长度
如下图:
在这里插入图片描述

(5)获取每个电影的名字

25个路径里面,每个路径里面有10个电影影的名字,共250个

li=html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li')
for item in li:
    name=item.xpath('')
  • 1
  • 2
  • 3
  • item为自己命名的,可理解为电影
  • name理解为电影名字
  • 整个语句可理解为,从25个xpath路径里面获取得250个电影,然后再从这250个电影(item)的xpath路径里面获取250个电影名(name
    现在复制两个电影名的链接进行分析
    第一页的肖申克的救赎:
/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]
  • 1

第一页的霸王别姬:

/html/body/div[3]/div[1]/div/div[1]/ol/li[2]/div/div[2]/div[1]/a/span[1]
  • 1

可看出,两个链接只有/li[]中的数字不一样
代码表示:

 li=html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li')
       for item in li:
       name=item.xpath('./div/div[2]/div[1]/a/span[1]')
  • 1
  • 2
  • 3

此处的点表示上面写的li后面括号里跟的所有路径,因为此处name后面写的是第一页的名字的共同特征,故只输出第一页的所有电影名字,结果如下:
在这里插入图片描述跟上面提取‘风华绝代’之时一样,上图中显示的结果为一个数组,可在代码后加[0],输出纯文字,如下图所示:
在这里插入图片描述

(6)接着获取电影链接

先复制两个电影链接进行分析,以第一页为例(大致做法和获取名字相同)
第一页的肖申克的救赎:

/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a
  • 1

第一页的霸王别姬:

/html/body/div[3]/div[1]/div/div[1]/ol/li[2]/div/div[2]/div[1]/a
  • 1

可看出,两个链接只有/li[]中的数字不一样
代码表示:

 li=html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li')
       for item in li:
       dy_url=item.xpath('./div/div[2]/div[1]/a/@href')[0]
  • 1
  • 2
  • 3

此处的点表示上面写的li后面括号里跟的所有路径,因为此处dy_url(自己写的)后面写的是第一页的链接的共同特征,/@href为输出链接时的后缀,与上述输出电影名字文本类型时的/text()意义相同,程序中带有之前输出电影名字的部分,故只输出第一页的所有电影名字和电影链接,结果如下:
在这里插入图片描述

(7)接着获取电影星级数

先复制两个电影星级数进行分析,以第一页为例(大致做法和(4)、(5)名字相同)
第一页的肖申克的救赎:

/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[1]
  • 1

第一页的霸王别姬:

/html/body/div[3]/div[1]/div/div[1]/ol/li[2]/div/div[2]/div[2]/div/span[1]
  • 1

可看出,两个链接只有/li[]中的数字不一样
代码表示:

 li=html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li')
       for item in li:
       rating=item.xpath('./div/div[2]/div[2]/div/span[1]/@class')[0]
  • 1
  • 2
  • 3

此处的点表示上面写的li后面括号里跟的所有路径,因为此处rating(自己写的)后面写的是第一页的星级数的共同特征,/@class为输出星级数时的后缀,与上述输出电影名字文本类型时的/text()意义相同,结果如下:
在这里插入图片描述

(8)接着获取电影评分

先复制两个电影评分进行分析,以第一页为例(大致做法和(4)、(5)、(6)名字相同)
第一页的肖申克的救赎:

/html/body/div[3]/div[1]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[2]
  • 1

第一页的霸王别姬:

/html/body/div[3]/div[1]/div/div[1]/ol/li[2]/div/div[2]/div[2]/div/span[2]
  • 1

可看出,两个链接只有/li[]中的数字不一样
代码表示:

li=html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li')
 for item in li:
 rating_num=item.xpath('./div/div[2]/div[2]/div/span[2]')
  • 1
  • 2
  • 3

运行结果如下:
在这里插入图片描述

(9)接着获取电影评价人数

和上述方法一样,不再叙述
在这里插入图片描述

5.python综合输出的方法
(1)可以输出分隔符美化输出结果

在这里插入图片描述 print("~"*90)语句为输出分隔符,其中,*90表示输出90个波浪符号,分隔符的长度横着排列,当长度超过屏幕长度时,会自动从第二行开始排列,分隔符类型还可以自己变换,如下图,换成90个——符号也可以
在这里插入图片描述

(2)print横向同时输出多个值

运行结果如下在这里插入图片描述
不想输出的值可在print前面加#,变为注释,注释不运行

6.爬取得到的内容的保存问题
(1)常见保存格式

txthtml,涉及表格内容的可用excelcsv保存等
本次主要将上述爬取的内容放到csv格式中
为了方便保存,在电脑上建一个文件夹,然后在文件夹处输入cmd命令进入控制台,这样可以在打开jupyter notebook时直接打开之前写的代码
以上爬取的内容中,如评价人数中,显示的是人数和评价两个字,但很多时候我们只要数字,所以接下来将会介绍如何用正则表达式获取数字,以及爬取内容的保存问题

(2)爬取电影排名

为了运行出来时好看,将爬取的排名放到爬取内容的第一个
在这里插入图片描述

(3)用正则表达式re匹配星级数中的数字

如爬取到的星级数为rating5-trating4.5-t,但我们只想要数字,故用正则表达式来匹配
re正则表达式语法较复杂,平时可在网上多学习
准备工作:引入re包,import re
以分离rating5-t为例,运行结果如下:
在这里插入图片描述

  • test为自己命名,re.findall为语法结构,原为:
re.findall('rating5-t', test)
  • 1

因为想要把5替换了,故将5的位置改为(.*?)

  • 注意,re查找替换内容的过程中,找的只是要替换内容的最近的两个边界,如上述图片中,若将括号内改为(‘ting(.*?)-’, test),和原来(‘rating(.*?)-t’, test)相比,去掉了rat,仍能定位到5并运行出来,如下:
    在这里插入图片描述
    只要保留离5最近的g和-,其余在rating5-t中的不论怎么变都能输出5

  • 以提取“zzy旷love张kjh”这句话中的zzy love kjh为例
    在这里插入图片描述
    可以发现,最后的kjh没有显示出来,因为从右边开始读取,kjh后面找不到第一个边界(双引号不是语句中的内容,故不能作为kjh的最近的边界),在kih后面加上一个边界,(字母,文字,数字均可,此处我加了1314),如下图
    在这里插入图片描述

  • 提取评价中的评价人数(从右边开始读取,故左边第一个没有边界照样能读出来)
    在这里插入图片描述

(4)用专门提取数字的re正则来提取数字

上一步中是用(.*?)的方法来提取需要的内容,接下来将介绍专门提取所需数字的re正则表达式,运用时根据需求自主选择即可
在这里插入图片描述

  • 双引号中不写替代内容时:
    在这里插入图片描述
  • 将评价人数的两种正则方式做对比
    在这里插入图片描述
  • 将所有的评价人数中的人数正则出来
    在这里插入图片描述
(5)提取所有的星级数并将其规范化

快速注释及解除方法,Ctrl+/
在这里插入图片描述
注意此处的写法:
在这里插入图片描述赋值时从右边开始,故图中rating1=rating2但不等于rating3,rating3=rating4

  • 提取出来后,发现4.5级的星级数显示的是45,故要将其规范化,将5改为5分,45改为4.5分
    分析:5变为5分,可不用除以一个数,但45要变为4.5,要除以10,而我们现在要做的就是判断什么时候要除以一个数
  • 假设我们按数字的位数来判断,当数字为两位数时就除以10,下面用一个函数来判断一组数中的数字位数
    在这里插入图片描述
    此时出错了,因为第3行中len(fen)求的是fen中数字的长度,而len()函数中只能求字符串的长度,不能求数字的长度,故要用str()函数将fen转化为字符串,如下图
    在这里插入图片描述
  • 数字的长度已经判断出来,此时我们要做的就是当数字长度为1位时,保持不变,数字长度为2位时,就除以10,如下图
    在这里插入图片描述
  • 以上的操作只是正式开始前的局部示范,接下来将豆瓣top250上面的星级数(以第一页为例)全部提取并规范化
    在这里插入图片描述注意红色圈起的部分
(6)将爬取的到的内容保存为csv格式

导入csv,可直接在一个import后面一次性导入多个内容

  • 运行步骤及代码如下图
    在这里插入图片描述
    此处要注意圈起部分,写文件夹路径时,并不是将完整的文件夹路径全部填上,而是只要尾部的文件夹名

运行后编辑页面下方没有内容出现,但是打开自己进入jupyter notebook的新建文件夹处,出现了一个豆瓣250.csv的文件
在这里插入图片描述
打开豆瓣250.csv这个文件后,界面为:

在这里插入图片描述打开时有可能为乱码,可将文件夹删除重新写入,或将encoding='utf-8-sig'改为encoding='utf-8-sig'

  • 将爬取所有内容放入豆瓣250.csv中(下列两张图为所有完整代码)
    在这里插入图片描述在这里插入图片描述运行结果为:(共25个)
    在这里插入图片描述
    最后一行的fp.close()不能写在for item in li:的循环中,否则会被提前关闭

  • 写入成功后打开豆瓣250.csv文件如下:
    在这里插入图片描述到此爬取豆瓣top250第一页数据并保存成功!

7.所有代码综合

一次性获取页面上250个电影的内容,爬取所有250个页面的内容

#爬取所有250个页面的内容(所有代码综合)
import re,csv,requests
from lxml import etree

#1.设置浏览器代理,构造字典
headers={

    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/74.0'
}
  
#2.创建并打开文件夹,写入内容

fp = open("./豆瓣250.csv",'a',encoding='utf-8-sig')
writer=csv.writer(fp)
writer.writerow(('排名','名称','链接','星级','评分','评价人数'))

#3.循环所有页面
for page in range(0, 226, 25):
    print("正在获取第%s页"%page)
    url='https://movie.douban.com/top250?start=%s&filter='%page
   
# 4.请求源代码,向服务器发出请求
    reponse=requests.get(url=url,headers=headers).text

#5.看做筛子筛取数据    
    html_etree = etree.HTML (reponse)

#6.过滤
    li=html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li')
    for item in li:
        rank=item.xpath('./div/div[1]/em/text()')[0]   #电影排名

        name=item.xpath('./div/div[2]/div[1]/a/span[1]/text()')[0] #电影名字

        dy_url=item.xpath('./div/div[2]/div[1]/a/@href')[0]       #电影链接

        rating=item.xpath('./div/div[2]/div[2]/div/span[1]/@class')[0]  #电影星级数相关处理(如5星级)
        rating=re.findall('rating(.*?)-t', rating)[0]
        if len(rating)==2:             #rating为字符串,故直接求长度
            star = int(rating) / 10    #字符串不可做运算,故int()转化为整数型
        else:
            star=rating
    
        rating_num=item.xpath('./div/div[2]/div[2]/div/span[2]/text()')[0] #电影分数(如9.0分)

        content=item.xpath('./div/div[2]/div[2]/div/span[4]/text()')[0]  #电影评价人数(如1234人评价)
        content=re.sub(r'\D',"", content)  #""中的替代部分可写可不写
    
      
#         print(rank,name,dy_url,star,rating_num,content)
    
    
        writer.writerow((rank,name,dy_url,star,rating_num,content))     #写入身体部分内容
fp.close()  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54

运行结果为:
在这里插入图片描述

注意,此处写入所有的电影内容,需要把之前的第一页获取产生的文件夹删除以后再做此操作,要不写入不成功
打开豆瓣250.csv,就有250个电影的信息了,如下图:
在这里插入图片描述
至此,爬取数据成功结束!

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/191203
推荐阅读
相关标签
  

闽ICP备14008679号