python 爬虫 关于过程中错误及问题的记录

it2026-02-12  8

一、安装库

需要安装有bs4、re、xlwt、sqlite3和requests 问题一:pip install request提示报错 ERROR: Could not find a version that satisfies the requirement request (from versions: none) ERROR: No matching distribution found for request 原因:需要安装的库是requests,不是request!!!

二、利用requests库爬取网页获取数据

链接:https://blog.csdn.net/weixin_43848422/article/details/109246324

三、利用bs4库解析数据

链接:https://blog.csdn.net/weixin_43848422/article/details/109246523

四、实例:爬虫豆瓣电影Top250数据

1.利用requests库得到指定一个URL的网页内容 出现报错:request() got an unexpected keyword argument ‘header’ 原因:关键字‘header’错误,应为headers 修正后代码为:

# 得到指定一个URL的网页内容 def askURL(url): # 用户代理,发送请求的时候,让豆瓣服务端理解这个是一个浏览器而不是爬虫(本质上告诉浏览器,我们可以接收什么水平的文件内容) head={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36'} html='' try: responses=requests.get(url,headers=head) responses.encoding='utf-8' html=responses.text print responses.status_code print html except Exception as e: print e

运行后可返回网页HTML字符串

2.爬取网页获取数据后,逐一解析数据 需要先定义全局变量,对所需字段写规则(利用正则表达式)

# 影片详情链接的规则(全局变量) findlink=re.compile(r'<a href="(.*?)">') # 创建正则表达式对象,表示规则(字符串的模式),r是忽视所有特殊符号的意思,(.*?)代表可以是任意字符 # 影片图片的规则 findImgSrc=re.compile(r'<img(.*?)src="(.*?)"',re.S) # 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>') # 概况 findInq=re.compile(r'<span class="inq">(.*?)</span>') # 影片相关内容 findBd=re.compile(r'<p class="">(.*?) </p>',re.S)

对网页源码逐一进行解析

# 爬取网页,获取数据 def getData(baseurl): datalist=[] for i in range(0,10): # 调用获取页面信息的函数10次 url=baseurl+str(i*25) html=askURL(url) # 保存获取到的网页源码 # 2.逐一解析数据 soup=BeautifulSoup(html,'html.parser') for i in soup.find_all('div',class_="item"): # 查找符合要求的字符串,形成列表,找div里类class属性(注意添加_)为item的内容 # print i # 测试查看电影item全部信息 data=[] # 保存一部电影的所有信息 i=str(i) # print i # 获取影片详情的链接 link=re.findall(findlink,i)[0] # re库用来通过正则表达式查找指定字符串 data.append(link) # 添加链接 imgSrc=re.findall(findImgSrc,i)[0] imgSrc=imgSrc[1] # 把前面那些alt、class之类的去掉 data.append(imgSrc) # 添加影片图片 title=re.findall(findTitle,i) # 是一个列表 if(len(title)==2): ctitle=title[0] data.append(ctitle) # 添加中文名 otitle=title[1].replace('/','') # 把/替换,即去掉无关的符号 data.append(otitle) # 添加外国名 else: data.append(title[0]) data.append(' ') # 如果没有外国名,则留空 rating=re.findall(findRating,i)[0] data.append(rating) # 添加评分 judge=re.findall(findJudge,i)[0] data.append(judge) # 添加评价人数 inq=re.findall(findInq,i) if(len(inq)!=0): inq=inq[0].replace('。',' ') # 去掉句号 data.append(inq) # 添加概况 else: data.append(' ') bd=re.findall(findBd,i)[0] bd=re.sub('<br(\s+)?/>(\s+)?',' ',bd) # 去掉<br/>,替换成空格 bd=re.sub('/',' ',bd) data.append(bd.strip()) # 去掉前后空格,添加详情 datalist.append(data) # 把处理好的一部电影信息放入datalist # for n in datalist: # 把250条数据都打印出来 # print json.dumps(n,encoding='utf-8',ensure_ascii=False) return datalist

3.保存数据 (1)保存数据到Excel表格中

def saveData(datalist,savepath): book=xlwt.Workbook(encoding='utf-8',style_compression=0) # 创建workbook对象 sheet=book.add_sheet('豆瓣电影Top250',cell_overwrite_ok=True) # 创建工作表,cell_overwrite_ok=True的意思是每一个单元格往里面写的时候,覆盖以前的内容 # worksheet.write(0,0,'hello') # 写入数据,第一个参数表示行,第二个参数表示列,第三个参数表示内容 col=('电影详情链接','电影图片链接','影片中文名','影片外文名','评分','评价数','概况','相关信息') for i in range(0,8): # 仅仅只是把列名写进去 sheet.write(0,i,col[i]) for i in range(0,250): print ('第%d条'%i) data=datalist[i] for j in range(0,8): sheet.write(i+1,j,data[j]) # 数据 book.save(savepath) # 保存

(2)保存数据到数据库中

# 保存到数据库 class DatabaseAcess: # 初始化属性(包括host、port、user、password和database) def __init__(self): self.__db_host='localhost' # 属性应私有 self.__db_port=3306 # 注意,端口是int类型,不能有引号,否则会报错 self.__db_user='root' self.__db_password='123456' self.__db_database='test' # 数据库名 # 连接数据库 def isConnection(self): self.__db=pymysql.connect( host=self.__db_host, port=self.__db_port, user=self.__db_user, password=self.__db_password, database=self.__db_database, charset='utf8' ) # 插入数据 def linesinsert(self,datalist): try: self.isConnection() global cursor cursor=self.__db.cursor() # data=datalist[0] # print datalist[0] # for index in range(len(data)): # data[index]='"'+data[index]+'"' # 给data里的每个值都加上双引号 for i in range(len(datalist)): data=datalist[i] for index in range(len(data)): data[index]='"'+data[index]+'"' # 给data里的每个值都加上双引号 sql='insert into `movieTop250`(info_link,pic_link,cname,ename,score,rated,instruction,info)value('+data[0]+','+data[1]+','+data[2]+','+data[3]+','+data[4]+','+data[5]+','+data[6]+','+data[7]+')' cursor.execute(sql) # sql='insert into `movieTop250`(info_link) value('+'"'+data[0]+'"'+')' # sql='insert into `movieTop250`(info_link,pic_link,cname,ename,score,rated,instruction,info)value('+data[0]+','+data[1]+','+data[2]+','+data[3]+','+data[4]+','+data[5]+','+data[6]+','+data[7]+')' # print sql # cursor.execute(sql) except Exception as e: print e finally: cursor.close() self.__db.commit() self.__db.close()

附上代码:

# !/usr/bin/python # -*- coding: UTF-8 -*- from bs4 import BeautifulSoup # 网页解析,获取数据 import re # 正则表达式,进行文字匹配 import requests import xlwt # 进行excel操作 import sqlite3 # 进行SQLite数据库操作 import json def main(): baseurl='https://movie.douban.com/top250?start=' # 1.爬取网页 datalist=getData(baseurl) savepath='.\\doubanmovieTop250.xls' # 数据保存在当前文件夹下的豆瓣电影Top250.xls中 # 3.保存数据 saveData(datalist,savepath) # askURL('https://movie.douban.com/top250?start=') # 影片详情链接的规则(全局变量) findlink=re.compile(r'<a href="(.*?)">') # 创建正则表达式对象,表示规则(字符串的模式),r是忽视所有特殊符号的意思,(.*?)代表可以是任意字符 # 影片图片的规则 findImgSrc=re.compile(r'<img(.*?)src="(.*?)"',re.S) # 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>') # 概况 findInq=re.compile(r'<span class="inq">(.*?)</span>') # 影片相关内容 findBd=re.compile(r'<p class="">(.*?) </p>',re.S) # 爬取网页,获取数据 def getData(baseurl): datalist=[] for i in range(0,10): # 调用获取页面信息的函数10次 url=baseurl+str(i*25) html=askURL(url) # 保存获取到的网页源码 # 2.逐一解析数据 soup=BeautifulSoup(html,'html.parser') for i in soup.find_all('div',class_="item"): # 查找符合要求的字符串,形成列表,找div里类class属性(注意添加_)为item的内容 # print i # 测试查看电影item全部信息 data=[] # 保存一部电影的所有信息 i=str(i) # print i # 获取影片详情的链接 link=re.findall(findlink,i)[0] # re库用来通过正则表达式查找指定字符串 data.append(link) # 添加链接 imgSrc=re.findall(findImgSrc,i)[0] imgSrc=imgSrc[1] # 把前面那些alt、class之类的去掉 data.append(imgSrc) # 添加影片图片 title=re.findall(findTitle,i) # 是一个列表 if(len(title)==2): ctitle=title[0] data.append(ctitle) # 添加中文名 otitle=title[1].replace('/','') # 把/替换,即去掉无关的符号 data.append(otitle) # 添加外国名 else: data.append(title[0]) data.append(' ') # 如果没有外国名,则留空 rating=re.findall(findRating,i)[0] data.append(rating) # 添加评分 judge=re.findall(findJudge,i)[0] data.append(judge) # 添加评价人数 inq=re.findall(findInq,i) if(len(inq)!=0): inq=inq[0].replace('。',' ') # 去掉句号 data.append(inq) # 添加概况 else: data.append(' ') bd=re.findall(findBd,i)[0] bd=re.sub('<br(\s+)?/>(\s+)?',' ',bd) # 去掉<br/>,替换成空格 bd=re.sub('/',' ',bd) data.append(bd.strip()) # 去掉前后空格,添加详情 datalist.append(data) # 把处理好的一部电影信息放入datalist # for n in datalist: # 把250条数据都打印出来 # print json.dumps(n,encoding='utf-8',ensure_ascii=False) return datalist # 得到指定一个URL的网页内容 def askURL(url): # 用户代理,发送请求的时候,让豆瓣服务端理解这个是一个浏览器而不是爬虫(本质上告诉浏览器,我们可以接收什么水平的文件内容) head={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36'} html='' try: responses=requests.get(url,headers=head) responses.encoding='utf-8' html=responses.text # print responses.status_code # print html except Exception as e: print e return html # 返回获取到的网络源码 # 保存数据 def saveData(datalist,savepath): book=xlwt.Workbook(encoding='utf-8',style_compression=0) # 创建workbook对象 sheet=book.add_sheet('豆瓣电影Top250',cell_overwrite_ok=True) # 创建工作表,cell_overwrite_ok=True的意思是每一个单元格往里面写的时候,覆盖以前的内容 # worksheet.write(0,0,'hello') # 写入数据,第一个参数表示行,第二个参数表示列,第三个参数表示内容 col=('电影详情链接','电影图片链接','影片中文名','影片外文名','评分','评价数','概况','相关信息') for i in range(0,8): # 仅仅只是把列名写进去 sheet.write(0,i,col[i]) for i in range(0,250): print ('第%d条'%i) data=datalist[i] for j in range(0,8): sheet.write(i+1,j,data[j]) # 数据 book.save(savepath) # 保存 if __name__=='__main__': main()
最新回复(0)