文章目录
-
- 一、准备工作
- 1.安装python3.7
- 2.安装爬取豆瓣top250所需包
- 二、爬取网页
- 1.分析网页
- 2.爬取网页
- 3.信息筛选
- 4.复制整个网页的xpath路径
- 5.获取第一页每个电影的名字
- 6.获取链接
- 7.评分
- 8.评价人数
- 9.排名
- 10.美化
- 11用正则表达式re匹配星级数中的数字
- 12.写入文件夹
一、准备工作
1.安装python3.7
打开浏览器搜索python,得到如下结果:
打开图片中箭头网址
或直接访问python官网打开得到以下画面
下拉网页
选择自己需要的版本
点击后面的download即可下载。
具体安装可以参考其他博友文章,这里不进行过多赘述。
2.安装爬取豆瓣top250所需包
所需要的包有,jupyter(个人习惯的编辑环境,可以不安装)、re(正则表达式)、request、lxml、csv
安装所需包的过程:电脑键盘按住win+R,打开控制台,输入cmd,点击确定或回车啊。
安装包的公式为pip install ******
以安装第一个包为例,输入pip install jupyter,回车,就可以在线安装了
初次安装会需要一些时间,耐心等待一会,其他的包同理。
二、爬取网页
1.分析网页
在此处我们爬取豆瓣电影top250的电影信息
打开可以看到网页如下
我们可以看到本页只有25部电影,我们的任务是爬取250部电影,共十页,分析每一页的区别,此处打开前三页和最后一页的网址对比
第一页
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=225&filter=
由分析我们可以知道,每一页的网址是差不多的,唯一的差别就是数字的变动,每一页的数值变化为25,
除此之外,其余部分都是一样的。我们可以用一个for循环数组代码来实现这个网页
运用range函数,可以得到十个间隔为25的数组
此处的是226,而不是225是因为range函数后面的括号为前闭后开区间,即为前可取后不可取,三个数字代表的含义分别为从0开始,到226结束,间隔25.
将start=0改为start=%s,后面跟的%page表示将page函数中的数 值范围赋予给s,即可一次性构造出十个网页的链接,代码如下:
for page in range(0, 226, 25):
url = 'https://movie.douban.com/top250?start=%s&filter='%page
print (url)
运行代码可以得到如下图结果:
至此,我们已经得到了十个网页的代码了。
2.爬取网页
打开豆瓣网页,对网页进行审查,
右击进入检查元素,点击网络(network),再点击所有(All)
对该网页进行刷新,下方会出现网页的组成元素,例如图片等
用箭头标出来的分别为请求方法和状态码,即我们使用的方法为get,返回的状态码为200则为成功,返回其他数值则不成功。
使用get语句访问浏览器,得到如下结果,意义为:系统识别出为非正常访问,拒绝返回值
此处我们需要伪装浏览器,用以躲过网站的识别,首先,讲代码审查中的用户代理复制过来,构造字典,用户代理的位置为:
豆瓣top250中右键检查,notework,all,下拉导航,出现的
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36
即为用户代理。
import requests
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'
}
requests.get(url=test_url,headers=headers)
运行即可得到状态码为200的返回值
在代码后加入.text,即可得到以下内容。
我们可以看到,我们虽然成功得爬取了网页数据,不过看上去是很杂乱的,我们还需要筛选数据。
我们加上一句代码
reponse=requests.get(url=test_url,headers=headers).text
#中间一行空格
reponse
3.信息筛选
工具:xpath,re,BeautifulSoup,工具需要提前安装,安装教程查看本文开头目录,这里不做过多赘述。
假如我要从网页信息中筛选出“这个杀手不太冷”的电影的名字
#从lxml包里面到处etree这个工具
from lxml import etree
#使用etree解析网页
html_etree = etree.HTML (reponse)
#定位
html_etree.xpath('//*[@id="content"]/div/div[1]/ol/li[4]/div/div[2]/div[1]/a/span[1]/text()')
得到如下结果
网页检查中的定位怎么查找:打开网页,找到你想查找的数据,点击检查,在出现的代码中找到你所选择的内容,右键copy xpath。在xpath后面添加/ text()后缀即可查找。
4.复制整个网页的xpath路径
打开网页,右击检查元素,找到每个电影模块对应的序列代码,如下图
将图中右侧鼠标选中的位置的xpath路径复制下来为:
第一个://[@id=“content”]/div/div[1]/ol/li[1]
第二个://[@id=“content”]/div/div[1]/ol/li[2]
第三个://*[@id=“content”]/div/div[1]/ol/li[3]
我们可以分析,每一部电影的结构都大致相似,只有最后的数字不一样。
将上面的代码表示出来为
html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li[1]')
html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li[2]')
html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li[3]')
将最后的[数字]删除,即可表示所有的xpath路径。即
html_etree.xpath('/html/body/div[3]/div[1]/div/div[1]/ol/li')
可以表示所有的路径。
输入len(li)即可查看路径长度
5.获取第一页每个电影的名字
item可以自己命名,name为电影名字,可自己命名
整个语句可理解为,从25个xpath路径里面获取得250个电影,然后再从这250个电影(item)的xpath路径里面获取250个电影名(name)
第一个://[@id=“content”]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a/span[1]
第二个://[@id=“content”]/div/div[1]/ol/li[2]/div/div[2]/div[1]/a/span[1]
可看出,两个链接只有/li[]中的数字不一样,
from lxml import etree html_etree = etree.HTML (reponse) 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]/text()') print(name)
得到如下结果:
后面加上[0],可以得到
6.获取链接
对电影的链接进行分析
第一个://[@id=“content”]/div/div[1]/ol/li[1]/div/div[2]/div[1]/a
第二个://[@id=“content”]/div/div[1]/ol/li[2]/div/div[2]/div[1]/a
只有li[]不一样,其他的都是一样的,做法同上一个获取电影名称
代码如下:
from lxml import etree
html_etree = etree.HTML (reponse)
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()')
print(name)
dy_url = item.xpath('./div/div[2]/div[1]/a/@href')
print(dy_url)
运行:
7.评分
第一个://[@id=“content”]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[1]
第二个://[@id=“content”]/div/div[1]/ol/li[2]/div/div[2]/div[2]/div/span[1]
同理,代码不一样
from lxml import etree
html_etree = etree.HTML (reponse)
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()')
print(name)
dy_url = item.xpath('./div/div[2]/div[1]/a/@href')[0]
print (dy_url)
rating = item.xpath('./div/div[2]/div[2]/div/span[1]/@class')[0]
print(rating)
8.评价人数
第一个://[@id=“content”]/div/div[1]/ol/li[1]/div/div[2]/div[2]/div/span[4]
第二个://[@id=“content”]/div/div[1]/ol/li[2]/div/div[2]/div[2]/div/span[4]
同理:
from lxml import etree
html_etree = etree.HTML (reponse)
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()')
print(name)
dy_url = item.xpath('./div/div[2]/div[1]/a/@href')[0]
print (dy_url)
rating = item.xpath('./div/div[2]/div[2]/div/span[1]/@class')[0]
print(rating)
content=item.xpath('./div/div[2]/div[2]/div/span[4]/text()')
print(content)
9.排名
原理同上
10.美化
输入’~’*50, 可以加波浪线,50为个数
11用正则表达式re匹配星级数中的数字
如爬取到的星级数为rating5-t或rating4.5-t,但我们只想要数字,故用正则表达式来匹配
re正则表达式语法较复杂,平时可在网上多学习
准备工作:引入re包,import re
我们首先要知道一些关于正则表达式的使用方法,正则表达式替换的方法是.*?替换。
例如:
import re
a = "123人评价"
re.findall('(.*?)人评价', a)
则输出为123.
这样输出的rating分数,还是有一点问题,那就是本来应该是4.5的变为了45,因此我们还需要设置一个条件语句,
if len(rating) == 2:
star = int(rating) / 10 #int()转化为数字
else:
star = rating
意义为当rating长度为2的时候,除以十,当rating长度不为2,就不改变。
12.写入文件夹
分为三个步骤,1.创建文件夹并打开
fp = open("./豆瓣top250.csv", 'a', newline='', encoding = 'utf-8-sig') writer = csv.writer(fp)
2.写入
writer.writerow(('排名', '名称', '链接', '星级', '评分', '评价人数'))
writer.writerow((rank, name, dy_url, star, rating_num, content))
3.关闭
插入代码中,运行即可
在此处我们看不到文件,返回jupyter文件夹,打开即可看到文件
打开可以看到
至此,我们本次任务完成。
代码汇总:
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]
# print (dy_url)
#评分
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()
通过本次作业,想说的是,自己不够认真,很多处小错误,然后查找错误花费了很多时间,一些问题自己无法解决,参考了同学的作业,总的来说需要多从实战之中获取经验。这次辛苦杨友同学老师了。