1、爬虫概念
网络爬虫,是一种按照一定规则,自动抓取互联网信息的程序或脚本。爬虫的本质是模拟浏览器打开网页,获取网页中我们想要的那部分数据。
2、基本流程(本次主要针对html文件)
具体描述可参考:爬虫基本原理(引用)
3、网页结构了解(重要)
由于爬虫的本质是模拟浏览器打开网页,所以我们需要了解HTTP 的操作过程。
HTTP即超文本传输协议。HTTP协议是用于从网络传输超文本数据到本地浏览器的传送协议,它能保证高效而准确地传送超文本文档。HTTPS是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,简称为HTTPS。
当准备爬取某网页时需通过按f12进入开发者模式,观察网页源代码(Elements中)以及浏览器和服务器端互相通信的信息(Network中)。如以下图片所示:
user-agent反映用户浏览器版本和操作系统,cookie存储用户加密信息,如果想爬取用户登录后的网页信息需要用到cookie。总之,需要注意Response Headers和Request Headers即响应头和请求头内的信息。还需注意请求方法get与post的区别与应用场景。
其中具体信息可参考Http基本原理(引用)
4、具体代码
方法名 | 功能 |
---|---|
askURL(url) | 得到指定一个URL的网页内容(返回值为html即一张网页源码) |
getData(baseurl) | 爬取所有网页并逐一解析数据(返回值为一个列表,每一项为一部电影信息) |
saveData(datalist,savepath) | 以xls文件的方式保存爬取的数据 |
init_db(dbpath) | 利用sqlite3 库创建数据表 |
saveData2DB(datalist,dbpath) | 在数据库中插入数据 |
main() | 调用主函数 |
from bs4 import BeautifulSoup #网页解析,获取数据
import re #正则表达式,进行文字匹配
import urllib.request,urllib.error #制定URL,获取网页数据
import xlwt #进行excel操作
import sqlite3 #进行SQLite数据库操作
def main():
baseurl="https://movie.douban.com/top250?start="
#1、爬取网页
datalist=getData(baseurl)
#savepath=".\\豆瓣电影Top250.xls"
dbpath="movie.db"
#3、保存数据
#saveData(datalist,savepath)
saveData2DB(datalist,dbpath)
#影片详情的链接的规则
findLink=re.compile(r'') #创建正则表达式对象,表示规则(字符串的模式)
#影片图片的链接的规则
findImgSrc=re.compile(r',re.S)#re.S让换行符包含在字符中
#影片片名
findTitle=re.compile(r'(.*)')
#影片评分
findRating=re.compile(r' ')
#找到评价人数
findJudge=re.compile(r'(\d*)人评价')
#找到概况
findInq=re.compile(r'(.*)')
#找到影片的相关内容
findBd=re.compile(r'(.*?)
',re.S)
#爬取网页
def getData(baseurl):
datalist=[]
for i in range(0,10):
url=baseurl+str(i*25) #调用获取页面信息的函数,10次
html=askURL(url) #保存获取到的网页源码
# 2、逐一解析数据
soup=BeautifulSoup(html,"html.parser")
for item in soup.find_all('div',class_="item"): #查找符合要求的字符串,形成列表
#print(item) #测试:查看电影item所有信息
data=[]#保存一部电影的所有信息
item=str(item)
#影片详情的链接
link=re.findall(findLink,item)[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)#添加评价人数
inq=re.findall(findInq,item)
if len(inq)!=0:
inq=inq[0].replace("。","")#去掉句号
data.append(inq)#添加概述
else:
data.append(" ")#留空
bd=re.findall(findBd,item)[0]
bd=re.sub('
(\s+)?'," ",bd) #去掉
bd=re.sub('/'," ",bd)#替换/
data.append(bd.strip())#去掉前后的空格
datalist.append(data) #把处理好的一部电影信息放入datalst
# print(datalist)
return datalist
#得到指定一个URL的网页内容
def askURL(url):
head={ #模拟浏览器头部信息,向豆瓣服务器发送消息
"User-Agent": "Mozilla / 5.0(Windows NT 10.0;WOW64) AppleWebKit / 537.36(KHTML, likeGecko) Chrome / 56.0.2924.90Safari / 537.36 2345Explorer / 9.3.0.17248"
}#用户代理,表示告诉服务器我们是什么类型的机器、浏览器(本质上是告诉浏览器我们可以接收什么水平的文件内容)
request=urllib.request.Request(url,headers=head)
html=""
try:
response=urllib.request.urlopen(request)
html=response.read().decode("utf-8")
except urllib.error.URLError as e:
if hasattr(e,"code"):#判断e这个对象里面是否包含code这个属性
print(e.code)
if hasattr(e,"reason"):
print(e.reason)
return html
#3、保存数据
def saveData(datalist,savepath):
book = xlwt.Workbook(encoding="utf-8",style_compression=0) # 创建workbook对象
sheet = book.add_sheet('豆瓣电影Top250',cell_overwrite_ok=True) # 创建工作表
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,introduction,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,
introduction text,
info text
)
'''#创建数据表
conn=sqlite3.connect(dbpath)
cursor=conn.cursor()
cursor.execute(sql)
conn.commit()
conn.cursor()
if __name__=="__main__": #当程序执行时
main() #调用函数
print("爬取完毕")