Python案例实操1-网络爬虫
案例1:使用Python爬虫、sqlite技术爬取x半电影Top250的电影数据,并保存成Excel文件和数据库文件
- 新建.py文件,定义程序运行的入口
if __name__ == "__main__":
pass
- 分析爬取的网址信息
x半电影TOP250,分析网址的规律,点击下一页可以发现每次点击都会在网址后面拼接上start参数,参数表示上一页结束新一页开始 - 开始爬取网页, 爬取网页过程就是解析数据的过程,里面会使用到urllib.request模块获取网页数据、BeautifulSoup模块解析数据、re正则表达式模块匹配查找数据等
def getData(baseurl):
"""爬取网页"""
datalist = []
for i in range(0, 10): # 遍历页数
url = baseurl + str(i * 25) # 拼接URL,指定开始位置
html = askUrl(url)
# 解析网页数据
soup = BeautifulSoup(html, "html.parser")
for item in soup.find_all("div", class_="item"): # 遍历指定查找结果列表
data = [] # 保存电影信息
item = str(item) # 将item转成字符串
link = re.findall(patlink, item)[0] # 查找电影详情链接
data.append(link)
imgstr = re.findall(patimg, item)[0] # 电影图片
data.append(imgstr)
titles = re.findall(pattitle, item) # 电影名称,有多个名字
if len(titles) == 2:
data.append(titles[0]) # 中文名
data.append(titles[1].replace("/", "")) # 外文名, 去掉多余/
else:
data.append(titles[0])
data.append("") # 外文名留空
score = re.findall(patscore, item)[0] # 评分
data.append(score)
num = re.findall(patpeople, item)[0] # 评价人数
data.append(num)
desc = re.findall(patdesc, item) # 一句话描述
if len(desc) != 0:
data.append(desc[0])
else:
data.append("")
bd = re.findall(patbd, item)[0] # 背景信息
bd = re.sub("<br(\s+)?/>(\s+)?", "", bd.strip()) # 去除<br/>标签, strip()去空格
data.append(bd)
datalist.append(data)
return datalist
- 通过request请求数据时,经常会遇到反爬虫的网站,会报状态码418错误,需要我们手动设置headers来模拟正常用户请求,跳过反爬虫的拦截
def askUrl(baseurl):
"""获取指定URL网页数据"""
# 设置headers来模拟正常用户请求
header = {
"User-Agent": "Mozilla / 5.0(Windows NT 10.0; Win64; x64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 97.0.4692.99 Safari / 537.36 Edg / 97.0.1072.69"
}
req = urllib.request.Request(baseurl, headers=header)
response = urllib.request.urlopen(req)
html = response.read().decode("utf-8")
return html
- 解析得到我们所需要的数据后,使用sqlite模块保存到数据库文件中,方便后续对数据的处理(如词云生成,后面会有案例)
连接数据库,并建立movie表
def init_db(dbpath):
"""初始化数据库"""
conn = sqlite3.connect(dbpath)
# 获取游标
c = conn.cursor()
# 建表sql语句
sql1 = "drop table if exists movie;"
sql2 = '''
create table movie(
link_detail varchar not null,
link_img varchar,
c_title varchar not null,
o_title varchar,
score number,
num int,
desc varchar,
bd text
)
'''
c.execute(sql1)
c.execute(sql2)
conn.commit()
conn.close()
- 将数据保存到数据库中
def insert(datalist, dbpath):
"""数据库新增操作"""
conn = sqlite3.connect(dbpath)
c = conn.cursor()
print("%d 条数据待写入数据库" % len(datalist))
for move in datalist:
for index in range(0, len(move)):
if index == 4 or index == 5:
continue
move[index] = '"' + move[index].strip() + '"' # 给value加上双引号, 数字类型不用加
sql = '''
insert into movie(link_detail, link_img, c_title, o_title, score, num, desc, bd)
values(%s)
''' % ','.join(move) # value之间用,连接
c.execute(sql)
conn.commit()
c.close()
conn.close()
- 运行程序,生成movie.db数据库文件,大功告成!
- 附上程序完整代码 spider.py
import urllib.request
from bs4 import BeautifulSoup
import re
import xlwt
import sqlite3
# 匹配规则
# 电影详情
patlink = re.compile(r'a href="(.*?)">')
# 电影图片
patimg = re.compile(r'<img.*src="(.*?)"', re.S) # re.S:让换行符也包含在字符串中
# 电影名称
pattitle = re.compile(r'<span class="title">(.*?)</span>')
# 电影评分
patscore = re.compile(r'<span class="rating_num" property="v:average">(.*?)</span>')
# 影评人数
patpeople = re.compile(r'<span>(\d*)人评价</span>')
# 电影概况
patdesc = re.compile(r'<span class="inq">(.*?)</span>')
# 电影背景
patbd = re.compile(r'<p class="">(.*?)</p>', re.S)
def getData(baseurl):
"""爬取网页"""
datalist = []
for i in range(0, 10): # 遍历页数
url = baseurl + str(i * 25) # 拼接URL,指定开始位置
html = askUrl(url)
# 解析网页数据
soup = BeautifulSoup(html, "html.parser")
for item in soup.find_all("div", class_="item"): # 遍历指定查找结果列表
data = [] # 保存电影信息
item = str(item) # 将item转成字符串
link = re.findall(patlink, item)[0] # 查找电影详情链接
data.append(link)
imgstr = re.findall(patimg, item)[0] # 电影图片
data.append(imgstr)
titles = re.findall(pattitle, item) # 电影名称,有多个名字
if len(titles) == 2:
data.append(titles[0]) # 中文名
data.append(titles[1].replace("/", "")) # 外文名, 去掉多余/
else:
data.append(titles[0])
data.append("") # 外文名留空
score = re.findall(patscore, item)[0] # 评分
data.append(score)
num = re.findall(patpeople, item)[0] # 评价人数
data.append(num)
desc = re.findall(patdesc, item) # 一句话描述
if len(desc) != 0:
data.append(desc[0])
else:
data.append("")
bd = re.findall(patbd, item)[0] # 背景信息
bd = re.sub("<br(\s+)?/>(\s+)?", "", bd.strip()) # 去除<br/>标签, strip()去空格
data.append(bd)
datalist.append(data)
return datalist
def askUrl(baseurl):
"""获取指定URL网页数据"""
# 设置headers来模拟正常用户请求
header = {
"User-Agent": "Mozilla / 5.0(Windows NT 10.0; Win64; x64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 97.0.4692.99 Safari / 537.36 Edg / 97.0.1072.69"
}
req = urllib.request.Request(baseurl, headers=header)
response = urllib.request.urlopen(req)
html = response.read().decode("utf-8")
return html
def saveData(datalist, filepath):
"""保存数据到Excel文件中"""
workbook = xlwt.Workbook(encoding="utf-8") # 创建Workbook对象
sheet = workbook.add_sheet("豆瓣电影TOP250", cell_overwrite_ok=True) # 创建工作页
col = ("详情链接", "图片链接", "影片中文名", "影片外文名", "影片评分", "评分人数", "影片概述", "相关信息") # 标题
for i in range(0, len(col)):
sheet.write(0, i, col[i]) # 写入标题 参数:“行”, “列”, “内容”
for i in range(0, 250):
move = datalist[i] # 遍历影片信息 "行"
for j in range(0, len(col)): # "列"
sheet.write(i + 1, j, move[j]) # 注意:从第二行开始写入影片信息
workbook.save(filepath) # 保存到文件
def init_db(dbpath):
"""初始化数据库"""
conn = sqlite3.connect(dbpath)
# 获取游标
c = conn.cursor()
# 建表sql语句
sql1 = "drop table if exists movie;"
sql2 = '''
create table movie(
link_detail varchar not null,
link_img varchar,
c_title varchar not null,
o_title varchar,
score number,
num int,
desc varchar,
bd text
)
'''
c.execute(sql1)
c.execute(sql2)
conn.commit()
conn.close()
def insert(datalist, dbpath):
"""数据库新增操作"""
conn = sqlite3.connect(dbpath)
c = conn.cursor()
print("%d 条数据待写入数据库" % len(datalist))
for move in datalist:
for index in range(0, len(move)):
if index == 4 or index == 5:
continue
move[index] = '"' + move[index].strip() + '"' # 给value加上双引号, 数字类型不用加
sql = '''
insert into movie(link_detail, link_img, c_title, o_title, score, num, desc, bd)
values(%s)
''' % ','.join(move) # value之间用,连接
c.execute(sql)
conn.commit()
c.close()
conn.close()
def saveToSqlite(datalist, dbpath):
"""保存数据到Sqlite文件中"""
# 初始化数据库连接
init_db(dbpath)
# 将数据插入表中
insert(datalist, dbpath)
if __name__ == "__main__":
baseurl = "https://movie.douban.com/top250?start=";
# 1.爬取网页
datalist = getData(baseurl)
# 2.保存数据到Excel中
# filepath = "豆瓣电影TOP250.xls"
# saveData(datalist, filepath)
# 3.保存数据到sqlite
dbpath = "movie.db"
saveToSqlite(datalist, dbpath)
print("爬取成功!")