爬虫基础之爬取豆瓣同城信息(保存为csv excel 数据库)

devtools/2025/3/16 23:06:12/

网站:长沙最近一周戏剧活动_豆瓣
温馨提示: 本案例仅供学习交流使用

本案例所使用的模块
requests(发送HTTP请求)pandas(数据保存模块)
lxml(用于解析数据模块)csv(用于保存为csv文件)
pymysql(用于操作数据库)parsel(解析数据的模块)

确定爬取的信息内容:

  • 戏剧的名称
  • 戏剧的时间
  • 戏剧的地点
  • 戏剧的费用
  • 参与与感兴趣人数

爬取步骤:

  1. 发送请求 模拟浏览器向服务器发送请求
  2. 解析数据 提取我们想要的数据
  3. 保存数据 对数据进行持久化保存 如csv excel mysql

一.发送请求

查看源代码 查看是否为静态数据

打开快捷键 Ctrl+F 输入我们想要爬取的数据


能够搜索到的为 静态数据  不能搜索到的为动态数据由服务器返回的 需要找到相关的返回接口

开始写代码  构建请求
复制浏览器中的网址  请求中的数据在 网络中的标头中查看

python">url = f'https://www.douban.com/location/changsha/events/week-drama'

F12 or 右击检查 点击网络 Ctrl+R 刷新接口  随便点击一个数据包

这里面包含我们所有的请求信息  比如请求方式 请求地址 UA cookie等
一般我们复制 UserAgent Referer cookie 这三个信息

python"># 导包
import requestsfrom lxml import etreeheaders = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0','referer':'https://www.douban.com/location/changsha/','cookie':'你的cookie'
}
resp = requests.get(url, headers=headers)
print(resp.text)

打印我们请求到的网页信息 确认需要爬取的数据是否在里面

同样的在终端用Ctrl+F 快捷键打开搜索框 OK 数据在里头

二.解析数据

接着我们解析数据 使用lxml 中的etree模块进行解析

python"># 将页面解析成html
html = etree.HTML(resp.text)

然后我们分析网页页面  找到包含所有数据的标签 后续通过循环遍历提取
Explain: 用开发者工具上面的小箭头 去页面中分析结构

 我们取 ul class属性为events-list events-list-pic100 events-list-psmall 下面的li标签
 每一个li标签为一个戏剧

python">lis = html.xpath('//ul[@class="events-list events-list-pic100 events-list-psmall"]/li')

接着遍历循环 提取数据
name: 直接定位这个
itemprop="summary"的span标签 提取里面的文字

python">for li in lis:name = li.xpath('.//a/span[@itemprop="summary"]/text()')[0]# 提取出来的是个列表 我们取出来

time: class属性为event-time的li标签 提取里面的文本

打印查看文本 发现不是我们想要的格式  我们处理成想要的格式
将星期去掉 只保留日期和时间 去除换行符
将列表转换成字符串 去除空格 以一个空格分割

python">a = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')

打印出来看看结果  split 方法返回的是个列表通过取值得到我们想要的 之后做个字符串的拼接

python">    # 这里我们选择把 星期去掉 只要时间和具体的时间t = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')[0]i = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')[2]m = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')[-3]e = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')[-1]# 转换成我们想要的格式  中间以||字符隔开time = t + i + '||' + m + e


时间提取完毕
address:li标签下面meta标签中的itemprop=location 里面的content 属性

但我不要长沙两个字 后续提取的数据中都有 可以像之前那样处理 先转换成字符串 后分割索引取值 做个拼接 这里我一气呵成

python">    address = ''.join(li.xpath('.//li/meta[@itemprop="location"]/@content')).split(' ')[1] + ' ' + \''.join(li.xpath('.//li/meta[@itemprop="location"]/@content')).split(' ')[2]

接着提取费用: class属性为fee下面的strong标签 里面的文本

去除里面的文字只保留数值

python">fee = ''.join(li.xpath('.//li[@class="fee"]/strong/text()')).replace('元起', '').replace('元', '')

最后感兴趣人数和参与人数 class属性为counts下面的第一个和第三个span标签 提取里面的文本

与之前的一样 删除文字 只保留数值

python">    # 参与与感兴趣人数participate = ''.join(li.xpath('.//p[@class="counts"]/span[1]/text()')).replace('人参加', '')interesting = ''.join(li.xpath('.//p[@class="counts"]/span[3]/text()')).replace('人感兴趣', '')

到此我们所有的数据提取完毕
多页采集的话 分析url请求地址的变化即可

第二页即第四页的数据 

 我们发现页码从0开始30结束 步长为10
 构建循环 遍历

python">for page in range(0, 31, 10):url = f'https://www.douban.com/location/changsha/events/week-drama?start={page}'

三.保存数据

先将我们的数据保存到字典当中 在外面定义一个空列表 后续将字典添加到列表中

python"># 主体代码如下
data = []
for page in range(0, 31, 10):url = f'https://www.douban.com/location/changsha/events/week-drama?start={page}'headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0','referer':'https://www.douban.com/location/changsha/','cookie':'bid=BY8EGmm9qc8; _vwo_uuid_v2=D1D9F5E9C68A518ED23DD0F263091E11E|05339352015c3656f34b21db6f6d7fac; _pk_id.100001.8cb4=273b64a736ae847b.1740225141.; dbcl2="287338786:YzuvHMiOWzs"; push_noty_num=0; push_doumail_num=0; __yadk_uid=PRahUgXe0eJLiRZgpFZjUYaLI78zwXW2; __utmv=30149280.28733; _ga_RXNMP372GL=GS1.1.1741225615.2.0.1741225615.60.0.0; ck=qsD8; __utmc=30149280; __utmz=30149280.1741595670.20.11.utmcsr=cn.bing.com|utmccn=(referral)|utmcmd=referral|utmcct=/; frodotk_db="5213e2611a4c65c4f63ba7234ee5314c"; _ga=GA1.2.1489580265.1740970320; _gid=GA1.2.1344269174.1741598633; _ga_Y4GN1R87RG=GS1.1.1741598632.1.0.1741598634.0.0.0; loc-last-index-location-id="118267"; ll="118267"; ap_v=0,6.0; _pk_ref.100001.8cb4=%5B%22%22%2C%22%22%2C1741606351%2C%22https%3A%2F%2Fntp.msn.cn%2F%22%5D; _pk_ses.100001.8cb4=1; __utma=30149280.1636982792.1735051587.1741598189.1741606351.22; __utmt=1; __utmb=30149280.4.10.1741606351'}resp = requests.get(url, headers=headers)html = etree.HTML(resp.text)lis = html.xpath('//ul[@class="events-list events-list-pic100 events-list-psmall"]/li')dit = {}for li in lis:name = li.xpath('.//a/span[@itemprop="summary"]/text()')[0]# 这里我们选择把 星期去掉 只要时间和具体的时间t = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')[0]i = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')[2]m = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')[-3]e = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')[-1]# 转换成我们想要的格式time = t + i + '||' + m + e# 另外一种方法 处理时间# n = li.xpath('.//li[@class="event-time"]/text()')[1].replace('\n', '').replace(' ','')# address = ''.join(li.xpath('//ul[@class="event-meta"]/li[2]/text()')).replace('\n','').replace(' ','')# 电影费用  并只保留数值# 将前面的长沙去掉address = ''.join(li.xpath('.//li/meta[@itemprop="location"]/@content')).split(' ')[1] + ' ' + \''.join(li.xpath('.//li/meta[@itemprop="location"]/@content')).split(' ')[2]fee = ''.join(li.xpath('.//li[@class="fee"]/strong/text()')).replace('元起', '').replace('元', '')# 参与与感兴趣人数participate = ''.join(li.xpath('.//p[@class="counts"]/span[1]/text()')).replace('人参加', '')interesting = ''.join(li.xpath('.//p[@class="counts"]/span[3]/text()')).replace('人感兴趣', '')dit = {'name': name,'time': time,'fee': fee,'participate': participate,'interesting': interesting,'address': address,}data.append(dit)
pd.DataFrame(data).to_excel('city.xlsx', index=False)

以上为通过pandas保存为excel表格

保存为csv 文件方式

python"># 导入模块
import csv
#调用字典写入方法 写入文件  保存为csv的格式编码为utf-8-sig 不然会出现乱码
csv_writer = csv.DictWriter(open('city_csv.csv', 'w', encoding='utf-8-sig', newline=''),fieldnames=['name', 'time', 'fee', 'participate', 'interesting', 'address'])
# fieldnames 定义标头
# 写入表头
csv_writer.writeheader()

保存到数据库

前提需要建库建表 定义字段

python"># 导包
import pymysql# 获取连接
connect = pymysql.connect(user='root',password="112233",host='localhost',database='douban', )
# 拿到游标
cursor = connect.cursor()# 准备sql语句
sql = 'insert into city values(%s,%s,%s,%s,%s,%s)'
# 执行sql
cursor.executemany(sql, [(name, time, fee, participate, interesting, address)])
# 提交事务
connect.commit()

本次案例的所有源代码  供大家交流学习使用

python">import requests
from lxml import etree
import pandas as pd
import csv
import pymysql# csv_writer = csv.DictWriter(open('city_csv.csv', 'w', encoding='utf-8-sig', newline=''),
#                fieldnames=['name', 'time', 'fee', 'participate', 'interesting', 'address'])
# csv_writer.writeheader()# 获取连接
connect = pymysql.connect(user='root',password="112233",host='localhost',database='douban', )
cursor = connect.cursor()data = []
for page in range(0, 31, 10):url = f'https://www.douban.com/location/changsha/events/week-drama?start={page}'headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/133.0.0.0','referer':'https://www.douban.com/location/changsha/','cookie':'bid=BY8EGmm9qc8; _vwo_uuid_v2=D1D9F5E9C68A518ED23DD0F263091E11E|05339352015c3656f34b21db6f6d7fac; _pk_id.100001.8cb4=273b64a736ae847b.1740225141.; dbcl2="287338786:YzuvHMiOWzs"; push_noty_num=0; push_doumail_num=0; __yadk_uid=PRahUgXe0eJLiRZgpFZjUYaLI78zwXW2; __utmv=30149280.28733; _ga_RXNMP372GL=GS1.1.1741225615.2.0.1741225615.60.0.0; ck=qsD8; __utmc=30149280; __utmz=30149280.1741595670.20.11.utmcsr=cn.bing.com|utmccn=(referral)|utmcmd=referral|utmcct=/; frodotk_db="5213e2611a4c65c4f63ba7234ee5314c"; _ga=GA1.2.1489580265.1740970320; _gid=GA1.2.1344269174.1741598633; _ga_Y4GN1R87RG=GS1.1.1741598632.1.0.1741598634.0.0.0; loc-last-index-location-id="118267"; ll="118267"; ap_v=0,6.0; _pk_ref.100001.8cb4=%5B%22%22%2C%22%22%2C1741606351%2C%22https%3A%2F%2Fntp.msn.cn%2F%22%5D; _pk_ses.100001.8cb4=1; __utma=30149280.1636982792.1735051587.1741598189.1741606351.22; __utmt=1; __utmb=30149280.4.10.1741606351'}resp = requests.get(url, headers=headers)html = etree.HTML(resp.text)lis = html.xpath('//ul[@class="events-list events-list-pic100 events-list-psmall"]/li')dit = {}for li in lis:name = li.xpath('.//a/span[@itemprop="summary"]/text()')[0]# 这里我们选择把 星期去掉 只要时间和具体的时间t = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')[0]i = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')[2]m = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')[-3]e = ''.join(li.xpath('.//li[@class="event-time"]/text()')).strip().split(' ')[-1]# 转换成我们想要的格式time = t + i + '||' + m + e# 另外一种方法 处理时间# n = li.xpath('.//li[@class="event-time"]/text()')[1].replace('\n', '').replace(' ','')# address = ''.join(li.xpath('//ul[@class="event-meta"]/li[2]/text()')).replace('\n','').replace(' ','')# 电影费用  并只保留数值# 将前面的长沙去掉address = ''.join(li.xpath('.//li/meta[@itemprop="location"]/@content')).split(' ')[1] + ' ' + \''.join(li.xpath('.//li/meta[@itemprop="location"]/@content')).split(' ')[2]fee = ''.join(li.xpath('.//li[@class="fee"]/strong/text()')).replace('元起', '').replace('元', '')# 参与与感兴趣人数participate = ''.join(li.xpath('.//p[@class="counts"]/span[1]/text()')).replace('人参加', '')interesting = ''.join(li.xpath('.//p[@class="counts"]/span[3]/text()')).replace('人感兴趣', '')dit = {'name': name,'time': time,'fee': fee,'participate': participate,'interesting': interesting,'address': address,}# data.append(dit)# csv_writer.writerow(dit)sql = 'insert into city values(%s,%s,%s,%s,%s,%s)'cursor.executemany(sql, [(name, time, fee, participate, interesting, address)])connect.commit()# pd.DataFrame(data).to_excel('city.xlsx', index=False)

本次的案例到此结束 感谢大家的观看  您的点赞和关注是我更新的动力

也可以看看我之前的文章希望对你有帮助
 


http://www.ppmy.cn/devtools/167667.html

相关文章

贪心算法(6)(java)优势洗牌

题目: 给定两个长度相等的数组nums1和nums2,nums1相对于nums2的优势可以满足nums1【1】>nums[2]的索引的数目来描述。 返回nums1的任意排列,使其相对于nums2的透视最大化呀。 原理(贪心策略):田忌赛马 1.如果比不…

数据类设计_图片类设计之6_混合图形类设计(前端架构)

前言 学的东西多了,要想办法用出来.C和C是偏向底层的语言,直接与数据打交道.尝试做一些和数据方面相关的内容 引入 接续上一篇,讨论混合图形类设计 方法论-现在能做什么 这段属于聊天内容---有句话是这么说的:不要只埋头拉车,还要抬头看路。写代码也是…

蓝桥杯_LED模块

一 前言 还有四十多天将要进行蓝桥杯的比赛,接下来一个多月我将进行我的知识点的复习,争取在蓝桥杯提交一个满意的答卷 二 锁存器M74HC753M1R 在我这一年并没有进行在csdn上发布任何文章,这一年我学了stm32、51,还有部分理论知…

css梯形tab

效果&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Tab 示例</…

【go】函数类型的作用

Go 语言函数类型的巧妙应用 函数类型在 Go 语言中非常强大&#xff0c;允许将函数作为值进行传递和操作。下面详细介绍函数类型的各种妙用&#xff1a; 1. 回调函数 // 定义一个函数类型 type Callback func(int) int// 接受回调函数的函数 func processData(data []int, ca…

算力服务器主要是指什么?

随着科技的快速发展&#xff0c;人工智能也逐渐兴起&#xff0c;算力服务器也受到了各个企业的重视&#xff0c;本文就来为大家介绍一下算力服务器主要都是指什么吧&#xff01; 算力服务器对于人工智能领域来说&#xff0c;在深度学习模型的训练和推理过程中扮演着非常重要的角…

ngx_conf_read_token

Ubuntu 下 nginx-1.24.0 源码分析 - ngx_conf_read_token-CSDN博客 static ngx_int_t ngx_conf_read_token(ngx_conf_t *cf) {u_char *start, ch, *src, *dst;off_t file_size;size_t len;ssize_t n, size;ngx_uint_t found, need_space, last_space…

时序约束整理

输入输出约束 FPGA整体概念 (1) Tdin为从FPGA的IO口到FPGA内部寄存器输入端的延时; (2) Tclk为从FPGA的IO口到FPGA内部寄存器时钟端的延时; (3) Tus/Th为FPGA内部寄存器的建立时间和保持时间; (4) Tco为FPGA内部寄存器传输时间; (5) Tout为从FPGA寄存器输出…