首页IT科技python的网络爬虫(Python大作业-网络爬虫程序)

python的网络爬虫(Python大作业-网络爬虫程序)

时间2025-06-14 06:42:14分类IT科技浏览4116
导读:简介 此程序是本人大三时期的Python大作业,初学Python后所编写的一个程序,是一个网络爬虫程序,可爬取指定网站的信息。...

简介

此程序是本人大三时期的Python大作业            ,初学Python后所编写的一个程序                    ,是一个网络爬虫程序      ,可爬取指定网站的信息            。

本程序爬取的网站是Bangumi-我看过的动画         ,Bangumi是一个专注于二次元的收视进度管理网站                    ,在这里可以记录自己看过的动画和书籍            、玩过的游戏                    、听过的音乐等等         ,本程序爬取的正是作者本人看过的所有动画      ,读者若想爬取自己看过的动画                    ,可下载程序后             ,自行修改源代码中的相应网址                    。

本程序使用Python编写   ,使用PyCharm进行开发                   ,数据库使用MySQL数据库                 ,程序可将“Bangumi-我看过的动画            ”中的所有动画信息爬取下来,并保存至数据库和Excel表格中               ,亦可将爬取的网站html源码保存至本地                    ,作者还编写了一个JavaWeb程序   ,用网页的形式展示爬取到的所有动画信息      。

程序源代码及程序设计说明书可在下方GitHub链接处进行下载            ,供各位需要的人学习参考         。

GitHub链接:Python爬虫-Bangumi

程序代码

在此展示Python爬虫的完整代码                    ,代码不多做介绍      ,详细请看代码注释或程序设计说明书         ,若读者对JavaWeb展示爬取数据感兴趣                    ,可至文章开头处GitHub链接下载程序         ,进行了解                    。

import re import ssl import xlwt import pymysql import urllib.request import urllib.error from bs4 import BeautifulSoup # 主函数 def main(): print("开始爬取网站") ssl._create_default_https_context = ssl._create_unverified_context #全局取消证书验证 baseurl = "https://bangumi.tv/anime/list/430090/collect" #要爬取的网站-Bangumi我看过的动画 pagecount = getPageCount(baseurl) #获取要爬取的页面总数 datalist = getData(baseurl, pagecount) #爬取网页      ,获取网页数据                    ,并解析数据 saveDataToDatabase(datalist) #将数据保存至数据库 saveDataToExcel(datalist) #将数据保存至excel表格 print("网站爬取成功             ,完毕!!!") # 获取HTML页面内容 def getHTML(url): print("正在获取页面 "+url+" ......") headers = { #反反爬虫   ,模拟浏览器头部信息 "User-Agent": "Mozilla / 5.0(Windows NT 10.0; Win64; x64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 80.0.3987.122 Safari / 537.36" } request = urllib.request.Request(url, headers=headers) response = urllib.request.urlopen(request) html = response.read().decode("utf-8") print("页面获取成功") return html # 保存HTML页面 def saveHTML(html, page): print("正在保存页面"+str(page)+"......") fileobj = open("lib/html/page"+str(page)+".html", "w", encoding="utf-8") fileobj.write(html) fileobj.close() print("页面"+str(page)+"保存成功") # 获取要爬取的页面总数 def getPageCount(baseurl): pagecount = 0 #页面总数 html = getHTML(baseurl) print("正在获取页面总页数......") soup = BeautifulSoup(html, "html.parser") ul = soup.find("ul", id="browserItemList") li = ul.find("li") if li is None: #若ul标签里无li标签                   ,则表示页面总数为0                 ,即我看过的动画为0 pagecount = 0 else: div = soup.find("div", id="multipage") span = div.find("span", class_="p_edge") #页面过多的话,div标签里会有一个span标签               ,网站会将“当前页数/总页数                    ”放在此span标签中 if span is not None: #若有span标签                    ,则可以直接获取页面总数 result = re.findall(r[0-9]+, span.string) pagecount = int(result[1]) else: #若无span标签   ,则需通过a标签获取页面总数 alist = div.find_all("a") if len(alist) != 0: #若有a标签            ,则倒数第二个a标签的内容即为总页数 pagecount = int(alist[len(alist) - 2].string) else: #若无a标签                    ,则表示页面总数为1 pagecount = 1 print("页面总数获取成功      ,页面总数为{}页".format(pagecount)) return pagecount # 将网页中的链接由相对路径改为绝对路径         ,或修改不符合要求的链接 def changeLink(html): print("正在修改相关链接......") soup = BeautifulSoup(html, "html.parser") # 获取所有a标签                    ,对不符合要求的进行修改 a_list = soup.find_all("a") for i in a_list: #对链接为相对路径的a标签进行修改 if href in i.attrs and re.match(r/[^\s]*, i[href]) is not None: i[href] = "https://bangumi.tv" + i[href] # 获取所有link标签         ,对不符合要求的进行修改 link_list = soup.find_all("link") for i in link_list: #对链接为相对路径的link标签进行修改 if href in i.attrs and re.match(r/[^\s]*, i[href]) is not None: i[href] = "https://bangumi.tv" + i[href] # 获取所有script标签      ,对不符合要求的进行修改 script_list = soup.find_all("script") for i in script_list: #对链接为相对路径的script标签进行修改 if src in i.attrs and re.match(r/[^\s]*, i[src]) is not None: i[src] = "https://bangumi.tv" + i[src] # 获取所有form标签                    ,对不符合要求的进行修改 form_list = soup.find_all("form") for i in form_list: #对链接为相对路径的form标签进行修改 if action in i.attrs and re.match(r/[^\s]*, i[action]) is not None: i[action] = "https://bangumi.tv" + i[action] # 获取所有img标签             ,对不符合要求的进行修改 img_list = soup.find_all("img") for i in img_list: #为img标签的图片链接加上https:前缀 if src in i.attrs and re.match(r//[^\s]*, i[src]) is not None: i[src] = "https:" + i[src] # 发生未知错误   ,无法正确爬取获取该动画的img标签的src属性                   ,实属无奈                 ,故手动显式修改 if soup.find("li", id="item_7157") is not None: img = soup.find("li", id="item_7157").find("img") img[src] = "https://www.yuucn.com/wp-content/uploads/2023/05/1684521669-550a3fe0fd3c184.jpg" # 特殊情况,为我的头像的图片链接加上https:前缀 span = soup.find("span", class_="avatarNeue avatarSize75") span[style] = re.sub(r//[^\s]*, "https:" + re.search(r//[^\s]*, span[style]).group(), span[style]) # 特殊情况               ,修改特定a标签链接 div = soup.find("div", id="robot_speech") a = div.find("a", class_="nav") a[href] = "https://bangumi.tv/" + a[href] print("相关链接修改成功") return soup.prettify() # 将网页改为本地                    ,相关依赖使用本地资源   ,无需联网即可访问............ 暂不考虑实现 def toLocal(): pass # 爬取网页            ,获取网页数据                    ,并解析数据 def getData(baseurl, pagecount): datalist = [] #二维列表      ,用于存放所有我看过的动画 for i in range(1, pagecount+1): #遍历所有页面         ,一个一个爬取 url = baseurl + "?page=" + str(i) html = getHTML(url) #获取HTML页面内容 html = changeLink(html) #修改相关链接 saveHTML(html, i) #保存HTML页面 print("开始爬取解析页面"+str(i)) soup = BeautifulSoup(html, "html.parser") all_animation = soup.find("ul", id="browserItemList") #该ul标签中存放了目标数据                    ,即我看过的动画 # 逐一解析数据 for item in all_animation.find_all("li"): #遍历一个个li标签         ,即遍历一部部我看过的动画      ,并获取数据 data = [] # 获取id idd = re.search(r[0-9]+, item[id]).group() data.append(idd) print("正在解析动画(id:{})数据......".format(idd)) # 获取中文名 chinese_name = item.find("a", class_="l").string.strip() data.append(chinese_name) # 获取原名 if item.find("small", class_="grey") is None: #可能无原名 original_name = "" else: original_name = item.find("small", class_="grey").string.strip() data.append(original_name) # 获取话数      、放送开始时间         、导演等人 info = item.find("p", class_="info tip").string episodes = re.search(r[0-9]+, info).group() if re.search(r[\d]+年[\d]+月[\d]+日, info) is not None: #有两种日期格式 broadcast_time = re.search(r[\d]+年[\d]+月[\d]+日, info).group() broadcast_time = re.sub(r[^\d]+, "-", broadcast_time).strip("-") #转换为xxxx-xx-xx的格式 elif re.search(r[\d]+-[\d]+-[\d]+, info) is not None: broadcast_time = re.search(r[\d]+-[\d]+-[\d]+, info).group() else: broadcast_time = "" if re.search(r日.+, info) is None: #可能无导演等人 people = "" else: people = re.search(r日.+, info).group() people = people[4:].strip() data.append(episodes) data.append(broadcast_time) data.append(people) # 获取收藏时间 star_time = item.find("span", class_="tip_j").string.strip() data.append(star_time) # 获取个人评分 score = item.find("span", class_="starlight")[class][1] score = re.search(r[0-9]+, score).group() data.append(score) # 获取个人标签 if item.find("span", class_="tip") is None: #可能无个人标签 tag = "" else: tag = item.find("span", class_="tip").string tag = tag.strip()[4:] data.append(tag) # 获取页面网址 page_url = item.find("a", class_="l")[href] data.append(page_url) # 获取缩略封面图网址                    ,并下载保存 print("正在下载缩略封面图{}.jpg".format(idd)) low_image_url = item.find("img", class_="cover")[src] data.append(low_image_url) low_image_path = "lib/image/low/" + idd + ".jpg" data.append(low_image_path) low_image_url = re.sub(rlain.bgm, "bangumi", low_image_url) #图片原链接不允许爬取下载             ,故需转换下链接 urllib.request.urlretrieve(low_image_url, low_image_path) #下载缩略封面图 # 获取高清封面图网址   ,并下载保存 print("正在下载高清封面图{}.jpg".format(idd)) high_image_url = re.sub(r/s/, "/l/", low_image_url) #缩略图和高清图的网址仅有一字之差 data.append(high_image_url) high_image_path = "lib/image/high/" + idd + ".jpg" data.append(high_image_path) #urllib.request.urlretrieve(high_image_url, high_image_path) #下载高清封面图                   ,文件较大且多                 ,故很花时间 datalist.append(data) print("页面{}爬取解析成功".format(str(i))) return datalist # 将数据保存至数据库 def saveDataToDatabase(datalist): print("开始将数据保存至数据库") con = pymysql.connect(host="localhost", database="web_crawler", user="root", password="root") cur = con.cursor() sql = "insert into animation values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)" try: for data in datalist: print("正在保存动画(id:{})数据至数据库......".format(data[0])) cur.execute(sql, tuple(data)) con.commit() except: con.rollback() #发生错误时回滚 print("数据保存失败") else: print("数据保存成功") cur.close() con.close() # 将数据保存至excel表格 def saveDataToExcel(datalist): print("开始将数据保存至excel表") book = xlwt.Workbook(encoding="utf-8") #创建一个workbook,并设置编码 sheet = book.add_sheet("我看过的动画") colname = ("ID", "中文名", "原名", "话数", "放送开始时间", "导演/原作者/等制作人", "收藏时间", "个人评分", "个人标签", "页面网址", "缩略封面图网址", "缩略封面图本地路径", "高清封面图网址", "高清封面图本地路径") style = xlwt.easyxf(font: bold on) #样式               ,为列名加粗 for i in range(0, 14): #添加列名 sheet.write(0, i, colname[i], style) for i in range(0, len(datalist)): #添加数据 data = datalist[i] print("正在保存动画(id:{})数据至excel表......".format(data[0])) for j in range(0, 14): sheet.write(i + 1, j, data[j]) book.save("lib/excel/Bangumi-我看过的动画.xls") #保存excel表 print("数据保存成功") if __name__ == "__main__": main()

运行结果

代码编写完成后运行程序                    ,程序运行过程中会在控制台实时输出当前爬取进度

爬取完毕后   ,可看到成功导出html文件

成功下载封面图片

信息成功保存至数据库

成功保存至Excel表格

最后JavaWeb程序也成功展示爬取的数据

后记

本程序仅供学习和参考            ,请勿抄袭或另作他用         。

感谢观看                    ,有什么问题可在下方评论区进行评论      ,若觉得本文章写得不错         ,还请点个赞呢      。

关注我                    ,收看更多精彩!( • ̀ω•́ )✧求点赞                    、评论         、收藏      、关注

声明:本站所有文章         ,如无特殊说明或标注      ,均为本站原创发布                    。任何个人或组织                    ,在未征得本站同意时             ,禁止复制                    、盗用             、采集   、发布本站内容到任何网站                   、书籍等各类媒体平台             。如若本站内容侵犯了原著者的合法权益   ,可联系我们进行处理   。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
vue 全局状态(VUE3 自定义 轻量级全局数据共享方案之一 Provide&inject (简单快速实现vuex功能)) win10 怎么更改密码(win10修改密码教程)