python爬虫之爬取豆瓣电影top250实战教学

前言:这是我带领2017级信管班同学学习python爬虫的第一课,我自学python爬虫差不多有一年的时间,实战了大量的网站,对python爬虫我自己的理解。本来上学期就想带领大家一起学习的,但是学校的教室不方便申请,加上大家都比较忙,所以未能进行。假期我帮忙很多大四的学生设计毕业论文,他们有很多人做数据挖掘与分析方面的设计,但是自己连什么是爬虫?爬虫可以用来干什么?都不理解,写这方面的论文实在是为难自己。本学期由于受到疫情的影响,我们只能在家进行网课教学,所以上课的时间很灵活。这个学期曾老师教我们数据分析,如果班上的同学还会使用python爬虫,无论是在以后论文上,亦或是工作中,都是一大助力,教学力在必行。我使用培训机构公开课的教学方式,带领大家使用python爬取《豆瓣电影TOP250》信息进行实战。我们班开过《web网页设计基础》和《大数据技术与运用》两门课程,正好涵盖了网络数据挖掘的基础,我只需要帮大家搭下桥,带领大家学懂python爬虫技能并不难。

视频链接: 腾讯课堂
操作环境: windows10, python37, jupyter, 谷歌浏览器
目标网站: 豆瓣电影 Top 250


1、分析网页

1.1、为什么要先分析网页

当我们拿到一个网页的时候,第一步并不是去测试它能否能使用 requests 简单请求到 html ,而是要去选择合适的方法进行爬取该网页,弄明白它数据的加载方式,才可以让我们的事半功倍,选择一个好的请求方法也可以提升我们爬虫程序的效率。

1.2、如何分析网页结构

我就以该课堂的内容为例, 进入 豆瓣电影 Top 250,查看它的网页结构。点击 “下一页” ,查看它的URL(链接,也叫统一资源定位符),会发现下面的规律:
在这里插入图片描述
链接测试: 除了第一页,我们随便挑选一页,换直接放在浏览器中访问看看,是否与当前的内容一致,如果没有问题,就可以直接用访问链接的方式,使用python的requests库去代替浏览器请求网页的服务器,返回HTML文件,提取并保存信息,再生成下一页的链接,继续上面请求服务器的操作爬取信息。

生成链接:
只需要写一个for循环,生成从0到225的数字即可,从上面的链接可以看出来,它的间隔为25, for page in range(0, 226, 25) 必须要取超过停止数据225,因为255不包含在其中,25是它的公差,程序表示为:
在这里插入图片描述



2、请求服务器

接下来就是向服务器发出请求了,我们先选择第一个链接来进行测试,完成本页所有内容的获取,然后再获取所有页面的信息
请求四部曲:

2.1、导入包 import requests

  • 如果没有安转 requests , 可以使用pip直接安转
  • 步骤:win+r,运行————>cmd,回车,————>pip install requests

2.2、设置浏览器代理

  • 网页点击右键,打开检查,选择Network,All,刷新网页,选择第一个文件,双击,选择headers
    在这里插入图片描述

  • 设置的浏览器代理必须为字典型,如:

headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
}

2.3、请求服务器格式

  • 请求源代码,向服务器发出请求,200代表成功
  • 如果在后面加上 .text 表示输出文本内容
  • test_url 是用一个链接,第二个 headers 是用来做浏览器代理的内容
requests.get(url = test_url, headers = headers)

2.4、请求服务器代码汇总

import requests
#pip安转 pip install requests————>win+r,运行————>cmd,回车,————>pip
test_url = 'https://movie.douban.com/top250?start=0&filter=' #''格式化,为字符串

#设置浏览器代理,它是一个字典
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
}

#请求源代码,向服务器发出请求,200代表成功
reponse = requests.get(url = test_url, headers = headers).text
# 快捷键运行,Ctrl+Enter

3、xpath提取信息

xpath是按照HTML标签的方式进行定位的,谷歌浏览器自带有xpath, 直接复制来就可以使用,简单方便,运行速度快。

3.1、获取xpath节点方法

在这里插入图片描述

3.2、xpath提取内容

我们使用xpath时,也必须先对网页进行 lxml 库中的 etreej解析 ,把它变为特有的树状形式,才能通过它进行节点定位。

from lxml import etree #导入解析库
html_etree = etree.HTML(reponse) # 看成一个筛子,树状

3.2.1、提取文本

当我们提取标签内的文本时,需要在复制到的xpath后面加上/text() ,告诉它说我需要提取的内容是一个标签呈现的数据,如《肖申克的救赎》:

<span class="title">肖申克的救赎</span>

xpath为:

//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]

提取文字:

name = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]/text()')
print ("这是数组形式:",name)
print ("这是字符串形式:",name[0])

结果:

这是数组形式: ['肖申克的救赎']
这是字符串形式: 肖申克的救赎

3.2.2、提取链接

每一个链接都是在标签内的,通常放在src=" " 或者 href=" " 之中,如
在这里插入图片描述
xpath为:

//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a

提取链接:
提取链接时,需要在复制到的xpath后面加上/@href , 指定提取链接

movie_url = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/@href')
print ("这是数组形式:",movie_url)
print ("这是字符串形式:",movie_url[0])

结果:

这是数组形式: ['https://movie.douban.com/subject/1292052/']
这是字符串形式: https://movie.douban.com/subject/1292052/

3.2.3、提取标签元素

这个网页中电影的星级没有用几颗星的文本表示,而是标签表示的,如:
在这里插入图片描述
所以只需要取出 class=" "中的内容就可以得到星级了,复制它的xpath,和提取链接的方法一样,在后面加上 /@class 即可

rating = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[1]/@class')
print ("这是数组形式:",rating)
print ("这是字符串形式:",rating[0])

结果:

这是数组形式: ['rating5-t']
这是字符串形式: rating5-t

4、正则表达式匹配信息

我们需要把结果中的信息匹配出来,可以使用正在表达式,单独提取自己需要的信息,如星级,它都是以 rating5-t 方式呈现的,但是我们只需要它数字5位置的部分,所以需要进行二次提取

4.1、提取固定位置信息

正则表达式中可以使用 .*? 来进行匹配信息,没有加括号时可以去掉不一样的信息,不需要提取出来,加括号 (.*?) 可以提取出括号内的内容,如:

import re
test = "rating5-t"
text = re.findall('rating(.*?)-t', test)
print (text)

结果:

['5']

分析讲解:
在这里插入图片描述

4.2、匹配出数字

比如评价数,我们xpath提取到的数据格式为: 1056830人评价 ,保存的时候只需要数字即可,现在把数字提取出来:

import re 
data = "1059232人评价"
num = re.sub(r'\D', "", data)
print("这里的数字是:", num)

结果:

这里的数字是: 1059232

5、提取本页所有信息

我们通过上面的 xpath 只能提取到一条信息,如果我们要提取所有的信息,写一个 for 循环把它遍历出来即可

先复制几个电影名字的 xpath,如前三个的:
在这里插入图片描述
li 标签前的作为父级,后面的为子集,./ 代替父级的位置,改写为:

li = html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li')
for item in li:
    name = item.xpath('./div/div[2]/div[1]/a/span[1]/text()')[0]
    print (name)

结果:

肖申克的救赎
霸王别姬
阿甘正传
这个杀手不太冷
美丽人生
泰坦尼克号
千与千寻
辛德勒的名单
盗梦空间
忠犬八公的故事
海上钢琴师
三傻大闹宝莱坞
楚门的世界
机器人总动员
放牛班的春天
星际穿越
大话西游之大圣娶亲
熔炉
疯狂动物城
无间道
龙猫
教父
当幸福来敲门
怦然心动
触不可及

结果分析: 按照这种方法,就可以遍历出其中的所有信息


6、内容写入CSV文件

保存内容与把大象放进冰箱是一样的,分别为打卡冰箱,把大象装进去,关闭冰箱,三部曲:

  1. 打开文件夹
  2. 放进文件夹
  3. 关闭文件夹
import csv
# 创建文件夹并打开
fp = open("./豆瓣top250.csv", 'a', newline='', encoding = 'utf-8-sig')
writer = csv.writer(fp) #我要写入

# 写入内容
writer.writerow(('排名', '名称', '链接', '星级', '评分', '评价人数'))

#关闭文件
fp.close()

7、代码汇总

import requests, csv, re
from lxml import etree

#设置浏览器代理,它是一个字典
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36'
}

# 创建文件夹并打开
fp = open("./豆瓣top250.csv", 'a', newline='', encoding = 'utf-8-sig')
writer = csv.writer(fp) #我要写入
# 写入内容
writer.writerow(('排名', '名称', '链接', '星级', '评分', '评价人数'))

for page in range(0, 226, 25): #226
    print ("正在获取第%s页"%page)
    url = 'https://movie.douban.com/top250?start=%s&filter='%page
    
    #请求源代码,向服务器发出请求,200代表成功,回退对其,Ctrl+]
    reponse = requests.get(url = url, headers = headers).text
    # 快捷键运行,Ctrl+Enter
    html_etree = etree.HTML(reponse) # 看成一个筛子,树状
    # 过滤
    li = html_etree.xpath('//*[@id="content"]/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]
        rating = re.findall('rating(.*?)-t', rating)[0]
        if len(rating) == 2:
            star = int(rating) / 10  #int()转化为数字
        else:
            star = rating
    #     注释ctrl+?

        rating_num = item.xpath('./div/div[2]/div[2]/div/span[2]/text()')[0]
        content = item.xpath('./div/div[2]/div[2]/div/span[4]/text()')[0]
        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()

jupyter结果截屏:
在这里插入图片描述

CSV文件截屏:
在这里插入图片描述

  • 13
    点赞
  • 41
    收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:技术黑板 设计师:CSDN官方博客 返回首页
评论 4

打赏作者

阿优乐扬

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值