Python爬虫实战

article/2025/9/12 8:00:36

文章目录

  • 1. 引言
  • 2. 页面分析
    • 2.1 页面元素分析
    • 2.2 分页分析
    • 2.3 页面详情页面
    • 2.4 下载链接
  • 3. 代码
    • 3.1 数据库结构
    • 3.2 步骤
      • 3.2.1 根据url获取页面结构
      • 3.2.2 解析页面数据
      • 3.2.3 数据存入数据库
  • 4. 测试结果
  • 5. 完整代码

1. 引言

注:勿用于非法用途。

之前学习过Python的基础知识,目前需要做语音识别和语义分析相关工作,所有又得继续学习Python

下面就学习下如何使用Python进行爬虫,就当练练手吧。

Python 特点:

  • Python是一种面向对象的脚本语言,使用时无需编译,因此也称作解释性语言,其结构简单,语法规则明确,关键词定义较少,非常适合初学者。

  • Python拥有丰富的内置库函数,对于处理网络、文件、GUI、数据库、文本等十分便捷,同时支持大量第三方库,比如最常用的用于科学计算的NumpySciPy等库,提供了非常简洁、高效的开发平台。

2. 页面分析

2.1 页面元素分析

下面要爬虫的是一个电影网站。本人平时看电影,都是用这个网站,想把爬完的数据存入mysql数据库,再用RUOYI开源项目做一个后台管理系统。

这个电影网站的分类共有20个,动作片、剧情片、爱情片、喜剧片……但它们都很有规律,查看网页源码,可以发现:

在这里插入图片描述

<a href="/0/">剧情片</a> 
<a href="/1/">喜剧片</a> 
<a href="/2/">动作片</a> 
<a href="/3/">爱情片</a> 
<a href="/4/">科幻片</a> 
<a href="/5/">动画片</a> 
<a href="/6/">悬疑片</a> 
<a href="/7/">惊悚片</a> 
<a href="/8/">恐怖片</a> 
<a href="/9/">纪录片</a> 
<a href="/11/">音乐歌舞题材电影</a> 
<a href="/12/">传记片</a> 
<a href="/13/">历史片</a> 
<a href="/14/">战争片</a> 
<a href="/15/">犯罪片</a> 
<a href="/16/">奇幻电影</a> 
<a href="/17/">冒险电影</a> 
<a href="/18/">灾难片</a> 
<a href="/19/">武侠片</a> 
<a href="/20/">古装片</a> 

对于每个分类的完整地址,前面都会加上网站域名。自己加上吧。

2.2 分页分析

对于每个电影类别的首页,地址都是:

域名 + /2/index.html

对于每个的电影院类别,从第二页开始,地址都是:

域名 + /2/index_2.html # 第二页

域名 + /2/index_3.html # 第三页

域名 + /2/index_4.html # 第四页

可以看出规律了吧。

2.3 页面详情页面

对于进入页面详情页,要观察页面列表的结构,入下图:

在这里插入图片描述

a标签指定了跳转的具体路径和电影的名称,还有评分,这几个信息可以获取到。

2.4 下载链接

进入得到电影详情页后,可以看到如下页面结构:

在这里插入图片描述

这样就可以获取到电影额下地址啦。

注意:此处的下载地址可能不止一个。

3. 代码

3.1 数据库结构

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;-- ----------------------------
-- Table structure for t_video_film
-- ----------------------------
DROP TABLE IF EXISTS `t_video_film`;
CREATE TABLE `t_video_film`  (`film_type` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`film_type_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`film_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`film_score` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`film_link` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`film_magnet_1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`film_magnet_2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,`film_magnet_3` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;

需要安装pymysql

pip installl pymysql

3.2 步骤

3.2.1 根据url获取页面结构

'''功能:访问 url 的网页,获取网页内容并返回参数:url :目标网页的 url返回:目标网页的 html 内容
'''
def get_data(url):headers = {'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8','user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',}try:r = requests.get(url, headers=headers)r.encoding="GBK"r.raise_for_status()return r.textexcept requests.HTTPError as e:print(e)print("HTTPError")except requests.RequestException as e:print(e)except:print("Unknown Error !")

此处要注意的是,要查看爬虫网站的编码,不然会乱码,具体如下:

在这里插入图片描述

3.2.2 解析页面数据

使用BeautifulSoup进行页面解析,具体可以参考另一篇文章:

https://blog.csdn.net/zxd1435513775/article/details/120280335

'''功能:提取 html 页面信息中的关键信息,并整合一个数组并返回参数:html 根据 url 获取到的网页内容返回:存储有 html 中提取出的关键信息的数组
'''
def parse_data(html):bsobj = bs4.BeautifulSoup(html, 'html.parser')info = []# 获取电影列表tbList = bsobj.find_all('table', attrs={'class': 'tbspan'})# 对电影列表中的每一部电影单独处理for item in tbList:movie = []score = item.find_all('tr')[2].find_all('td')[1].find_all('font')[1].textlink = item.b.find_all('a')[1]# 获取电影的名称name = link["title"]# 获取详情页面的 urlurl = 域名 + link["href"]# 将数据存放到电影信息列表里movie.append('20')movie.append('古装片')movie.append(name)movie.append(score)movie.append(url)try:# 访问电影的详情页面,查找电影下载的磁力链接temp = bs4.BeautifulSoup(get_data(url), 'html.parser')tbody = temp.find_all('tbody')# 下载链接有多个(也可能没有),这里将所有链接都放进来for i in tbody:download = i.a.textmovie.append(download)# print(movie)# 将此电影的信息加入到电影列表中info.append(movie)except Exception as e:print(e)return info

3.2.3 数据存入数据库

def save_data(data):db = pymysql.connect(host='localhost', user='root', password='', port=3306, db = 'film')cur = db.cursor()  ##获取游标sql3 = 'insert into t_video_film(film_type,film_type_name,film_name) values(%s,%s,%s)'sql4 = 'insert into t_video_film(film_type,film_type_name,film_name,film_score) values(%s,%s,%s,%s)'sql5 = 'insert into t_video_film(film_type,film_type_name,film_name,film_score,film_link) values(%s,%s,%s,%s,%s)'sql6 = 'insert into t_video_film(film_type,film_type_name,film_name,film_score,film_link,film_magnet_1) values(%s,%s,%s,%s,%s,%s)'sql7 = 'insert into t_video_film(film_type,film_type_name,film_name,film_score,film_link,film_magnet_1,film_magnet_2) values(%s,%s,%s,%s,%s,%s,%s)'sql8 = 'insert into t_video_film(film_type,film_type_name,film_name,film_score,film_link,film_magnet_1,film_magnet_2,film_magnet_3) values(%s,%s,%s,%s,%s,%s,%s,%s)'for i in data:print(i)if len(i) == 3:cur.execute(sql3, (i[0], i[1], i[2]))elif len(i) == 4:cur.execute(sql4, (i[0], i[1], i[2], i[3]))elif len(i) == 5:cur.execute(sql5, (i[0], i[1], i[2], i[3], i[4]))elif len(i) == 6:cur.execute(sql6, (i[0], i[1], i[2], i[3], i[4], i[5]))elif len(i) == 7:cur.execute(sql7, (i[0], i[1], i[2], i[3], i[4], i[5], i[6]))else:cur.execute(sql8, (i[0], i[1], i[2], i[3], i[4], i[5], i[6], i[7]))db.commit()

对于有多个下载链接的电影,要单独处理。

4. 测试结果

在这里插入图片描述

在这里插入图片描述

5. 完整代码

代码仅供参考,有很多可以优化的地方。

import requests
import bs4
import pymysqldef get_data(url):'''功能:访问 url 的网页,获取网页内容并返回参数:url :目标网页的 url返回:目标网页的 html 内容'''headers = {'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8','user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36',}try:r = requests.get(url, headers=headers)r.encoding="GBK"r.raise_for_status()return r.textexcept requests.HTTPError as e:print(e)print("HTTPError")except requests.RequestException as e:print(e)except:print("Unknown Error !")def parse_data(html):'''功能:提取 html 页面信息中的关键信息,并整合一个数组并返回参数:html 根据 url 获取到的网页内容返回:存储有 html 中提取出的关键信息的数组'''bsobj = bs4.BeautifulSoup(html, 'html.parser')info = []# 获取电影列表tbList = bsobj.find_all('table', attrs={'class': 'tbspan'})# 对电影列表中的每一部电影单独处理for item in tbList:movie = []score = item.find_all('tr')[2].find_all('td')[1].find_all('font')[1].textlink = item.b.find_all('a')[1]# 获取电影的名称name = link["title"]# 获取详情页面的 urlurl = 域名 + link["href"]# 将数据存放到电影信息列表里movie.append('20')movie.append('古装片')movie.append(name)movie.append(score)movie.append(url)try:# 访问电影的详情页面,查找电影下载的磁力链接temp = bs4.BeautifulSoup(get_data(url), 'html.parser')tbody = temp.find_all('tbody')# 下载链接有多个(也可能没有),这里将所有链接都放进来for i in tbody:download = i.a.textmovie.append(download)# print(movie)# 将此电影的信息加入到电影列表中info.append(movie)except Exception as e:print(e)return infodef save_data(data):'''功能:将 data 中的信息输出到文件中/或数据库中。参数:data 将要保存的数据'''# print(data)db = pymysql.connect(host='localhost', user='root', password='123456', port=3306, db = 'film')cur = db.cursor()  ##获取游标sql3 = 'insert into t_video_film(film_type,film_type_name,film_name) values(%s,%s,%s)'sql4 = 'insert into t_video_film(film_type,film_type_name,film_name,film_score) values(%s,%s,%s,%s)'sql5 = 'insert into t_video_film(film_type,film_type_name,film_name,film_score,film_link) values(%s,%s,%s,%s,%s)'sql6 = 'insert into t_video_film(film_type,film_type_name,film_name,film_score,film_link,film_magnet_1) values(%s,%s,%s,%s,%s,%s)'sql7 = 'insert into t_video_film(film_type,film_type_name,film_name,film_score,film_link,film_magnet_1,film_magnet_2) values(%s,%s,%s,%s,%s,%s,%s)'sql8 = 'insert into t_video_film(film_type,film_type_name,film_name,film_score,film_link,film_magnet_1,film_magnet_2,film_magnet_3) values(%s,%s,%s,%s,%s,%s,%s,%s)'for i in data:print(i)if len(i) == 3:cur.execute(sql3, (i[0], i[1], i[2]))elif len(i) == 4:cur.execute(sql4, (i[0], i[1], i[2], i[3]))elif len(i) == 5:cur.execute(sql5, (i[0], i[1], i[2], i[3], i[4]))elif len(i) == 6:cur.execute(sql6, (i[0], i[1], i[2], i[3], i[4], i[5]))elif len(i) == 7:cur.execute(sql7, (i[0], i[1], i[2], i[3], i[4], i[5], i[6]))else:cur.execute(sql8, (i[0], i[1], i[2], i[3], i[4], i[5], i[6], i[7]))db.commit()'''
<a href="/0/">剧情片</a> 6687/6804
<a href="/1/">喜剧片</a> 4203/4263
<a href="/2/">动作片</a> 3698/3756
<a href="/3/">爱情片</a> 2518/2561
<a href="/4/">科幻片</a> 1256/1258  
<a href="/5/">动画片</a> 936/988
<a href="/6/">悬疑片</a> 1424/1428
<a href="/7/">惊悚片</a> 3759/3792
<a href="/8/">恐怖片</a> 1547/1563
<a href="/9/">纪录片</a> 237/238
<a href="/11/">音乐歌舞题材电影</a>  289/289
<a href="/12/">传记片</a> 418/430
<a href="/13/">历史片</a> 568/572
<a href="/14/">战争片</a> 637/652
<a href="/15/">犯罪片</a> 2198/2227
<a href="/16/">奇幻电影</a> 1276/1279
<a href="/17/">冒险电影</a> /1727  58
<a href="/18/">灾难片</a> 81/81 3
<a href="/19/">武侠片</a> 75/75 3
<a href="/20/">古装片</a> 196/197 7
'''
def main():# 循环爬取多页数据for page in range(1, 8):print('正在爬取:第' + str(page) + '页......')# 根据之前分析的 URL 的组成结构,构造新的 urlif page == 1:index = 'index'else:index = 'index_' + str(page)url = 域名 + index + '.html'# 依次调用网络请求函数,网页解析函数,数据存储函数,爬取并保存该页数据html = get_data(url)movies = parse_data(html)save_data(movies)print('第' + str(page) + '页完成!')
if __name__ == '__main__':print('爬虫启动成功!')main()print('爬虫执行完毕!')

http://chatgpt.dhexx.cn/article/rdENMd9G.shtml

相关文章

insert into

7.insert into 如果我们想向表格中插入数据&#xff0c;就需要用到insert into语句了 7.1 insert into语法 INSERT INTO 表名 VALUES (值1, 值2,....) &#xff08;注&#xff1a;插入一行数据&#xff09; INSERT INTO 表名 (列名, 列名…

LaTeX: Missing } or { inserted. ^^I\For

报错 分析 可以发现&#xff0c;报错提示缺少{&#xff0c;但第306行并没有问题&#xff0c;并不缺少大括号。 这种情况下&#xff0c;很有可能是前面某个公式处出现了大括号缺失&#xff0c;建议从头到尾查找一遍。 修改 往前排查后发现某一处缺少大括号&#xff0c;如下所…

sqlserver触发器的使用以及inserted和deleted详解

背景&#xff1a;最近在项目中有需求是当人员表中有变动时&#xff08;比如&#xff1a;增加人员、修改人员信息、删除人员信息&#xff09;需要把这张表中的变动的信息同步到它对应的日志表中。那么如果用代码写逻辑的话在执行效率上会比较慢&#xff0c;正好sqlserver提供了触…

insert和insertSelective区别

使用逆向工程生成的代码做一个添加时通常都会给出两个答案&#xff0c;如题目想要增加一条数据会让你选择insert或者insertSelective 两者的区别在于如果选择insert 那么所有的字段都会添加一遍即使没有值 <insert id"insert" parameterType"com.ego.pojo.Tb…

Inserted和Deleted在insert、update、delete的简单使用

Inserted和Deleted在insert、update、delete的简单使用 Inserted表和Deleted表,仅仅在触发器运行时存在。当insert、update、delete操作时&#xff0c;可使用借助两个表来输出&#xff08;使用OUTPUT关键字&#xff09;操作前后的数据的变化。 Insert Update Delete Insert…

定义自定义指令;inserted()、update()

自定义指令的意义&#xff1a;对普通DOM元素进行底层操作&#xff1b; 作用 &#xff1a;可以获取到底层的dom&#xff0c;拿到想要的节点&#xff0c;从而进行操作&#xff1b; 实际应用&#xff1a;可以通过指令知道什么时候dom创建完成&#xff0c;从而进行依赖dom的库的初…

29.VUE自定义指令directive和inserted

VUE自定义指令directive和inserted 1.什么事自定义指令1.2使用自定义指令的方式 2.设置自定义组件2.1 设置全局指令2.2 设置私有指令2.3 钩子函数3. 案例 1.什么事自定义指令 指令 (Directives) 是带有 v- 前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式 (v-for 例…

echarts中x轴 y轴配置(字体颜色,线的颜色,分割线,y周单位颜色)。vue中直接使用echarts以及vue中使用vue-echarts如何配置横向渐变与纵向渐变(后者适用于前者)

vue中直接使用echarts //var myChart this.$echarts.init(document.getElementById("echart-twoline")); //vue var myChart echarts.init(document.getElementById("echart-twoline"));//jquery var option {backgroundColor: "#323a5e",…

Echarts折线图X轴Y轴图例位置调整

当X轴数据过多时Echarts会默认显示一半 如下图只显示奇数月份 Echarts加入axisLabel然后将interval设置为0就会将横轴全部显示 看一下效果 但是信息太多,看起来黏在了一起,我们可以让它-30度角倾斜显示 同样在axisLabel将rotate设置为-30,再看一下效果 这下都显示出来的,但…

修改echarts的x轴y轴的刻度和刻度线文本颜色和xy轴的轴线颜色和标题title的字体颜色

1&#xff0c;x轴y轴都是一样的&#xff1a; 1.1修改刻度文本颜色&#xff1a; 找到xAxis和yAxis&#xff1a; 添加如下代码&#xff1a;&#xff08;和data和type同级并列&#xff09; axisLabel: {show: true,textStyle: {color: #fff} } 如图&#xff1a; 1.2修改xy轴的轴…

转:echarts图表x,y轴的设置

转自&#xff1a; https://www.cnblogs.com/cjh-strive/p/11065005.html 每到用echarts这门技术去画图的时候&#xff0c;我们大多人都是直接从echarts的官网的案例找相应的案例直接把代码复制到开发软件上基本随便一改就能使用&#xff0c;但是这种情况基本都是在练习的时候和…

r语言plot函数x轴y轴名字_R语言中绘图的注释函数小结

我们知道一个漂亮而清晰的图像的形成指定缺不了图像中细节的注释。那么今天我们就来总结下在R语言中那些注释函数。 首先,我们看下文本注释函数:text(),mtext(), legend()。这些函数都是R语言内置的基础函数,我们看下具体的实例: 1. text() 注释绘图中的任意点。 其中主要…

echarts的x轴y轴的颜色改变

在操作echarts时&#xff0c;需求要求echarts的xy轴的颜色要与图形的颜色一致。 图1&#xff1a; 图2&#xff1a; 解决方案&#xff1a; 代码展示&#xff1a; var myChart1; $(function() { document.getElementById("begin1").flatpickr(); document.getEl…

r语言plot函数x轴y轴名字_Matplotlib入门-1-plt.plot( )绘制折线图

在Python学堂1-8中,我们通过一个实例(温湿度变化曲线对比分析图)对Matplotlib模块中的常用折线图进行了初步的认知学习。本章及后续几章内容是对前面内容的总结以及细化。系统性的带领大家共同学习Matplotlib中的众多知识点。 废话不多说,直接开始 Matplotlib模块的导入 im…

echarts如何优雅的去掉x轴y轴

option_column: {color: [#9D509F],grid: {left: 0,right: 0,bottom: 0,top: 0,// grid 区域是否包含坐标轴的刻度标签containLabel: false},xAxis: [{type: category,boundaryGap: false,data: [Mon, Tue, Wed, Thu, Fri, Sat, Sun],show: true}],yAxis: [{show: false,axisLi…

echarts柱形图X轴Y轴相关配置

可配置XY轴刻度线&#xff0c;字体大小&#xff0c;柱形图大小颜色等 const options {tooltip: {trigger: axis,axisPointer: {// 坐标轴指示器&#xff0c;坐标轴触发有效type: shadow // 默认为直线&#xff0c;可选为&#xff1a;line | shadow},textStyle: {// 鼠标hover…

echarts中的x轴y轴颜色,文字颜色改变

echarts中的x轴y轴颜色&#xff0c;文字颜色改变 原先的图改变颜色之后的图重点代码全代码 在更换背景之后&#xff0c;原图中的xy轴的颜色不明显或是想改变XY轴的颜色以及轴上的文字颜色。 原先的图 改变颜色之后的图 重点代码 axisLine:{lineStyle:{//改变xy轴线条的颜色col…

echarts markline X轴 Y轴 添加标识线

一、X轴添加标识线 效果&#xff1a; 代码&#xff1a; markLine: {symbol: [none, none],itemStyle: {normal: {lineStyle: {type: dashed,color: red,},label: {show: true,position: end,distance: 20,textStyle: {color : red,fontSize: 14,},formatter: function() {ret…

matplotlib中x轴y轴字号或字体修改

#修改matplotlib中x轴y轴字体大小 import matplotlib.pyplot as plt import numpy as np plt.rcParams[font.sans-serif][SimHei] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus]False #显示英文 plt.rcParams[font.size] 23 #设置字体大小&#xff0c;全局…