最近在学习爬虫的相关知识,跟着课程做了一个豆瓣的爬虫项目,爬虫部分有一百多行的代码,有一些复杂,下面贴上代码和跟着做的一些笔记,大家可以参考一下。
爬虫主要分为三个步骤 :
(1)爬取网页
在爬取网页时要注意模拟浏览器头部信息,将自己伪装成浏览器,向服务器发送消息,防止直接爬取时报错。
(2)逐一解析数据
在拿到爬取好的数据后,要解析数据,去掉没有用的,将需要的数据统一提取出来。
(3)保存数据
将数据存储在excel表中和数据库中,方便后续操作
# -*- codeing = utf-8 -*-
# @Time : 2022/7/9 10:23
# @Author : my
# @File : spider.py
# @Software : PyCharm
#import bs4 #网页解析,获取数据(将网页进行数据拆分)
from bs4 import BeautifulSoup #只调用BeautifulSoup这个模块
import re #正则表达式,进行文字匹配 (进行数据的提炼)
import urllib.request,urllib.error #制定URL,获取网页数据(给网页就可以爬取数据)
import xlwt #进行excel操作(将数据存放到excel中)
import sqlite3 #进行SQLite数据库操作(将数据库存放到数据库中)
def main():
baseurl = "https://movie.douban.com/top250?start="
#1.爬取网页
datalist = getDate(baseurl)
#savepath = "豆瓣电影Top250.xls" #按住ctrl会出现蓝色下划线,点击,就可以快速定义到下面对应的代码
dbpath = "movie.db"
#3.保存数据
#savaData(datalist,savepath)
saveData2DB(datalist,dbpath)
#askURL("https://movie.douban.com/top250?start=")
#影片链接
findLink = re.compile(r'<a href="(.*?)">') #创建正则表达式对象,表示规则
#影片图片
findImgSrc = re.compile(r'<img.*src="(.*?)"',re.S) #(.*?)表示字符0次到多次的出现,re.S让换行符包含在字符中
#影片片名
findTitle = re.compile(r'<span class="title">(.*)</span>')
#影片评分
findRating = re.compile(r'<span class="rating_num" property="v:average">(.*)</span>')
#影片评价人数
findJudge = re.compile(r'<span>(\d*)人评价</span>') #(\d*)表示有0-多个数字
#影片概况
findIng = re.compile(r' <span class="inq">(.*)</span>')
#找到影片的相关内容
findBd = re.compile(r'<p class="">(.*?)</p>',re.S)
#爬取网页
def getDate(baseurl):
datalist = []
for i in range(0,10):
url = baseurl + str(i*25)
html = askURL(url) #保存获取到的网页源码
# 2.逐一解析数据
soup = BeautifulSoup(html,"html.parser")
for item in soup.find_all('div',class_="item"):
#class加“_”,表示class属性,查找符合要求的所有字符串,形成列表
#print(item) #测试:查看一部电影的所有信息
data = []
item = str(item)
#影片详情的链接
link = re.findall(findLink,item)[0] #[0]表示只要找到的第一个字符串,re库通过正则表达式来查找指定字符串
data.append(link)
imgSrc = re.findall(findImgSrc,item)[0]
data.append(imgSrc)
titles = re.findall(findTitle,item) #片名可能只有一个中文名,没有外国名
if(len(titles)==2):
ctitle = titles[0] #添加中文名
data.append(ctitle)
otitle = titles[1].replace("/","") #去掉无关的符号
data.append(otitle) #添加外国名
else:
data.append(titles[0])
data.append(' ') #外国名若没有,要留空
rating = re.findall(findRating,item)[0]
data.append(rating)
judgeNum = re.findall(findJudge,item)[0]
data.append(judgeNum)
ing = re.findall(findIng,item)
if len(ing) != 0:
ing = ing[0].replace("。","") #去掉句号
data.append(ing) #添加概述
else:
data.append(" ")
bd = re.findall(findBd,item)[0]
bd = re.sub('<br(\s+)?/>(\s+)?'," ",bd) #去掉<br/>
bd = re.sub('/'," ",bd) #替换/
data.append(bd.strip())
datalist.append(data) #把处理好的一部电影信息放入datalist
#print(datalist)
return datalist
#得到指定一个URL的网页内容
def askURL(url):
head = { #模拟浏览器头部信息,将自己伪装成浏览器,向豆瓣服务器发送消息
"User-Agent": "Mozilla / 5.0(Windows NT 10.0;Win64;x64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 103.0.0.0Safari / 537.36"
#用户代理,表示告诉豆瓣服务器,我们是什么类型的机器,浏览器(本质上是告诉浏览器,我们可以接受什么水平的文件内容
}
request = urllib.request.Request(url,headers=head) #封装了一个url(访问的网站是什么),头部信息
html = "" #将它存到一个网站上
try:
response = urllib.request.urlopen(request)
html = response.read().decode("utf-8")
#print(html)
except urllib.error.URLError as e:
if hasattr(e,"code"):
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
#保存数据
def savaData(datalist,savepath):
print("save.....")
book = xlwt.Workbook(encoding="utf-8") #创建workbook对象
sheet = book.add_sheet('豆瓣电影Top250',cell_overwrite_ok=True) #创建工作表,cell_overwrite_ok表示每个单元存储的时候都要覆盖之前的内容
col=("电影详情链接","图片链接","影片中文名","影片外文名","评分","评价数","概况","相关信息")
for i in range(0,8):
sheet.write(0,i,col[i]) #列名
for i in range(0, 250):
print("第%d条" % (i + 1))
data = datalist[i]
for j in range(0, 8):
sheet.write(i + 1, j, data[j]) #数据
book.save(savepath)
def saveData2DB(datalist,dbpath):
init_db(dbpath)
conn = sqlite3.connect(dbpath)
cur = conn.cursor()
for data in datalist:
for index in range(len(data)):
if index == 4 or index == 5:
continue
data[index] = '"'+data[index]+'"'
sql = '''
insert into movie250(
info_link,pic_link,cname,ename,score,rated,instroduction,info)
values(%s)'''%",".join(data)
print(sql)
cur.execute(sql)
conn.commit()
cur.close()
conn.close()
def init_db(dbpath):
sql = '''
create table movie250
(
id integer primary key autoincrement,
info_link text,
pic_link text,
cname varchar,
ename varchar,
score numeric,
rated numeric,
instroduction text,
info text
)
''' #创建数据表
conn = sqlite3.connect(dbpath) #打开创建数据库
cursor = conn.cursor()
cursor.execute(sql)
conn.commit()
conn.close()
if __name__ =="__main__": #当程序执行时
#调用函数,是整个程序调用的入口
main()
print("爬取完毕")
这是最后爬取完存放在excel中的样子