写爬虫一共需要写这几个函数:
函数 | 功能 |
---|---|
get_resource() | 获取网页解析网页 |
parse_html() | 用Xpath或者BS4筛选网页,返回资源列表 |
downland() | 根据上面返回的列表下载资源 |
main() | 函数的入口调用上面函数 |
get_resourse()函数
parse_html()函数
downland()函数
main()函数
全部代码实现
我们以爬取豆瓣影评为例子:庆余年-豆瓣影评
get_resourse()函数
user_agents = [
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36',
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3; rv:11.0) like Gecko",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
]
def get_resource(url, params=None, flag='html'):
headers = {
'Host': 'movie.douban.com',
'User-Agent': random.choice(user_agents)
}
# 使用requests发出请求
response = requests.get(url=url, params=params, headers=headers)
# 判断response的状态码
if response.status_code == 200:
# 判断flag
if flag == 'html':
return response.text
elif flag == 'media':
return response.content
else:
print('获取资源有误!')
说明:这个get_resourse()函数形式固定可以直接ctrl+c,ctrl+v
你需要修改的是上面headers里面的host,这个自己F12吧,然后点击network,筛选doc,自己找吧!!
注意!!
这里面flag='html’时候可以下载文本文件
flag="media"时候下载媒体文件(图片,音频,视频等)
parse_html()函数:
def parse_html(resource):
comment_list = []
soup = BeautifulSoup(resource, 'lxml')
comments = soup.select_one('#comments')
comment_items = comments.select('.comment-item')
for item in comment_items:
comment_info = item.select_one('.comment h3 .comment-info')
# 用户的头像
image = item.select_one('.avatar a img').get('src')
# 评价的用户名
username = comment_info.find('a').text
# 获取星级
star = comment_info.find('span', class_='rating')
# 有个人他没有星级评论,这里
if star:
star = star.get('title')
else:
# 如果这个家伙没有评论,就默认5星吧->力荐
star = '力荐'
# 评论内容
comment_text = item.find('span', attrs={'class': 'short'}).text
# 保存在一个列表中
comment = [username, star, image, comment_text]
# 将其添加到列表中
comment_list.append(comment)
return comment_list
说明这个要自己筛选/解析html网页,找到要爬取的网页按下F12分析,筛选出自己想要的标签。用Xpath或者BeautifulSoup命令
忘记的小伙伴点击这里:
Xpath:Xpath教程 CQG
BS4:BeautifulSoup教程 CQG
我建议大家学BS4,这个我比较擅长,我觉得好用
基本思路:
筛选你想要的东西然后以列表形式储存起来,然后遍历每个项,分别取用评论、星级、用户名。然后用列表储存起来,返回这个带有评论、星级、用户名的列表
下一步就轮到我们的downland()函数出场了
downland()函数
def downland(comment_list):
# 文件操作:这是你返回的列表 [[],[],[],[],[]]
# a 是追加模式,不然覆盖的话就剩下最后一页的了
with open('data/douban.csv', mode='a', newline='', encoding='utf-8') as fw:
writer = csv.writer(fw)
# 遍历评论列表
writer.writerows(comment_list)
print('保存完毕!')
我们下载列表成csv文件
忘记CSV文件操作的小伙伴点击这里:CSV储存格式-CQG
如果你要下载图片、视频等媒体文件,这就比较复杂了
因为它是媒体文件,我们get_resourse()函数的flag要传入
flag=‘media’,不再是默认的flag='html’了
下面给出下载图片的代码片段
一定要弄清楚如何下载媒体文件(图片,视频)
一定要理解flag="media"就是那个get_resourse()
downland_img(courses)
#返回的course列表 course=[['/files/course....','xxxx'],[],[],...]
#每个列表项:['/files/course....','xxxx']
#每个列表项:['图片路径','文字']
#python可以这样分别循环 图片、文字
#image循环列表项第一个路径
#title循环列表项第二个路径
#这么写
for image, title in courses:
url = 'http://www.codingke.com' + image
# 借助requests完成图片的获取
# 你现在回过头看我们写的getresourse函数
# 里面有两个1.flag=html, 2.flag=media
# 我们要下载媒体文件(图片,视频)需要用flag="media"获取网页
content = get_resourse(url, flag='media')
# 这个是用后面做文件名
filename = url.rsplit('/')[-1] # ['http://www.codingke.com/files/course/2019/03-05','170936087d5a394261.jpg']
print(filename)
# 保存
# 保存到本地媒体资源用[二进制写入]
# mode="wb"
with open('images/' + filename, mode='wb') as fw:
fw.write(content)
print('成功下载:', filename)
注意:downland()函数可能要写多个,比如你下载歌词、乐曲、歌手、专辑封面图片要分开下载
你就需要写很多downland():
downland_music()
downland_
main()函数
main函数灵活调用上面三个函数
if __name__ == '__main__':
url = 'https://movie.douban.com/subject/25853071/comments'
# 这些是网页url参数,我们切换页面时?后面的东西
params = {'status': 'P', 'limit': 20, 'sort': 'new_score'}
# 这是爬取多页评论用的
# 我们观察到每翻页一次params中的start就增长20
# 由于点击下一页,其实就是参数变化
for i in range(10):
n = i * 20
params['start'] = n
# 调用函数获取资源
# 每一页由于参数变化,就是不同链接
# 每一页爬取都要请求整个网页
resource = get_resource(url=url, params=params,flag='html')
# print(resource)
# 调用解析方法:bs4 获取所有的评论内容,并返回list内容
# 用BS4筛选
comment_list = parse_html(resource)
# 保存
downland(comment_list)
# 延时
time.sleep(5)
print('成功下载第{}页评论....'.format(i + 1))
说明:main函数就是调用上面的get_resourse()parse_html(),downland()
全部代码实现:
爬取庆余年豆瓣影评
# 评论信息爬取
# 豆瓣
import csv
import random
import re
import time
import requests
from bs4 import BeautifulSoup
from lxml import etree
user_agents = [
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36',
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3; rv:11.0) like Gecko",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
]
# 1。获取html
def get_resource(url, params=None, flag='html'):
headers = {
'Host': 'movie.douban.com',
'User-Agent': random.choice(user_agents)
}
# 使用requests发出请求
response = requests.get(url=url, params=params, headers=headers)
# 判断response的状态码
if response.status_code == 200:
# 判断flag
if flag == 'html':
return response.text
elif flag == 'media':
return response.content
else:
print('获取资源有误!')
# 2. 解析网页内容
# 采用方式:beautifulSoup4
def parse_html(resource):
comment_list = []
soup = BeautifulSoup(resource, 'lxml')
comments = soup.select_one('#comments')
comment_items = comments.select('.comment-item')
for item in comment_items:
comment_info = item.select_one('.comment h3 .comment-info')
# 用户的头像
image = item.select_one('.avatar a img').get('src')
# 评价的用户名
username = comment_info.find('a').text
# 获取星级
star = comment_info.find('span', class_='rating')
# 有个人他没有星级评论,这里
if star:
star = star.get('title')
else:
# 如果这个家伙没有评论,就默认5星吧->力荐
star = '力荐'
# 评论内容
comment_text = item.find('span', attrs={'class': 'short'}).text
# 保存在一个列表中
comment = [username, star, image, comment_text]
# 将其添加到列表中
comment_list.append(comment)
return comment_list
# 3. 封装:持久化保存(保存数据)
def downland(comment_list):
# 文件操作:csv [[],[],[],[],[]]
# a 是追加模式,不然覆盖的话就剩下最后一页的了
with open('data/douban.csv', mode='a', newline='', encoding='utf-8') as fw:
writer = csv.writer(fw)
# 遍历评论列表
writer.writerows(comment_list)
print('保存完毕!')
# 只在本类下调用运行,其他类导入的话程序不会运行
if __name__ == '__main__':
url = 'https://movie.douban.com/subject/25853071/comments'
params = {'status': 'P', 'limit': 20, 'sort': 'new_score'}
for i in range(10):
n = i * 20
params['start'] = n
# 调用函数获取资源
resource = get_resource(url=url, params=params)
# print(resource)
# 调用解析方法:bs4 获取所有的评论内容,并返回list内容
comment_list = parse_html(resource)
# 保存
downland(comment_list)
# 延时
time.sleep(5)
print('成功下载第{}页评论....'.format(i + 1))