实战教程:Python爬取北京新发地农产品价格数据并存储到MySQL
在农产品价格数据分析、市场行情监控等场景中,获取新发地的价格数据是很有价值的需求。本文将详细讲解如何使用Python实现北京新发地农产品价格数据的爬取,并将爬取到的数据存储到MySQL数据库中,帮助大家掌握网络爬虫与数据库操作的核心技能。
技术栈选型
- 网络请求 :使用
requests库发送HTTP请求,获取目标网站的接口数据。requests库简洁易用,能高效处理POST/GET等请求方式,满足接口调用需求。 - 数据解析 :目标接口返回JSON格式数据,使用Python内置的
json库解析数据,提取关键信息。 - 数据库操作 :使用
pymysql库连接MySQL数据库,实现数据表创建和数据插入操作,pymysql是Python操作MySQL的主流库,兼容性好、操作便捷。 - 其他 :
time库用于异常处理时的短暂休眠,避免频繁请求触发网站限制。
实现步骤详解
步骤1:环境准备
首先需要安装所需的Python库,执行以下命令:
bash
pip install requests pymysql
同时确保本地已安装MySQL数据库,并创建好对应的数据库(本文中数据库名为vegetables),后续代码会基于该数据库创建数据表。
步骤2:数据库连接与数据表创建
首先实现MySQL数据库的连接,并创建用于存储价格数据的数据表。数据表需要包含农产品分类、名称、价格区间、规格、产地、发布日期等字段。
python
import pymysql
# 连接MySQL数据库
conn = pymysql.connect(
host='localhost', # 数据库主机地址,本地为localhost
user='root', # 数据库用户名
password='123456', # 数据库密码
database='vegetables' # 提前创建的数据库名
)
cursor = conn.cursor()
# 创建数据表SQL语句
sql_create_table = """
CREATE TABLE IF NOT EXISTS xinfadi (
id INT(11) NOT NULL AUTO_INCREMENT,
category1 VARCHAR(255), # 一级分类
category2 VARCHAR(255), # 二级分类
name VARCHAR(255), # 农产品名称
low_price FLOAT, # 最低价
high_price FLOAT, # 最高价
avg_price FLOAT, # 平均价
spec_info VARCHAR(255), # 规格信息
place VARCHAR(255), # 产地
unit_info VARCHAR(255), # 单位
pub_date DATE, # 发布日期
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
"""
# 执行创建表操作
cursor.execute(sql_create_table)
步骤3:编写爬虫核心函数
核心逻辑是调用新发地的价格数据接口,循环获取多页数据,解析后插入数据库。需要注意设置请求头模拟浏览器访问,避免被网站拦截。
python
import requests
import json
import time
def crawl_and_store_data(db_conn, db_cur, page_start, page_end):
# 请求头,模拟浏览器访问
head = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
'Referer': 'http://www.xinfadi.com.cn/priceDetail.html'
}
# 循环爬取指定页码范围的内容
for page in range(page_start, page_end + 1):
url = 'http://www.xinfadi.com.cn/getPriceData.html'
# 构造请求参数
params = {
'limit': 20,
'current': page,
'pubDateStartTime': "",
'pubDateEndTime': "",
'prodPcatid': "",
'prodCatid': "",
'prodName': "",
}
# 发送POST请求获取数据
resp = requests.post(url, headers=head, data=params).text
# 解析JSON数据
resp_json = json.loads(resp)
list_json = resp_json['list']
# 遍历解析后的每条数据
for i in list_json:
try:
# 提取字段,为空时赋值空字符串
category1 = i['prodCat'] or ''
category2 = i['prodPcat'] or ''
name = i['prodName']
low_price = i['lowPrice']
high_price = i['highPrice']
avg_price = i['avgPrice']
spec_info = i['specInfo'] or ''
place = i['place'] or ''
unit_info = i['unitInfo'] or ''
pub_date = i['pubDate']
# 打印数据,方便调试
print(category1, category2, name, low_price, high_price, avg_price, spec_info, place, unit_info, pub_date)
# 插入数据到MySQL的SQL语句
sql_insert_data = """
INSERT INTO xinfadi (category1, category2, name, low_price, high_price, avg_price, spec_info, place, unit_info, pub_date)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
"""
# 执行插入操作
db_cur.execute(sql_insert_data, (
category1, category2, name, low_price, high_price, avg_price, spec_info, place, unit_info, pub_date
))
# 提交事务
db_conn.commit()
except Exception as e:
# 捕获异常并打印,休眠0.5秒避免频繁请求
print(f"数据处理异常:{e}")
time.sleep(0.5)
return True
步骤4:执行爬虫并释放资源
调用核心爬虫函数,指定爬取的页码范围(本文爬取1-20页),爬取完成后关闭数据库游标和连接,释放资源。
python
try:
# 调用爬虫函数,爬取1-20页数据
status = crawl_and_store_data(conn, cursor, 1, 20)
if status:
print("数据爬取完成!")
except Exception as e:
print(f"爬取过程异常:{e}")
# 关闭游标和连接
cursor.close()
conn.close()
完整代码整合
将上述代码整合,补充编码声明等细节,完整代码如下(编码设置为gbk适配中文,避免乱码):
python
# coding=gbk
import pymysql
import requests
import json
import time
def crawl_and_store_data(db_conn, db_cur, page_start, page_end):
head = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36',
'Referer': 'http://www.xinfadi.com.cn/priceDetail.html'
}
for page in range(page_start, page_end + 1):
url = f'http://www.xinfadi.com.cn/getPriceData.html'
params = {
'limit': 20,
'current': page,
'pubDateStartTime': "",
'pubDateEndTime': "",
'prodPcatid': "",
'prodCatid': "",
'prodName': "",
}
resp = requests.post(url, headers=head, data=params).text
resp_json = json.loads(resp)
list_json = resp_json['list']
for i in list_json:
try:
category1 = i['prodCat'] or ''
category2 = i['prodPcat'] or ''
name = i['prodName']
low_price = i['lowPrice']
high_price = i['highPrice']
avg_price = i['avgPrice']
spec_info = i['specInfo'] or ''
place = i['place'] or ''
unit_info = i['unitInfo'] or ''
pub_date = i['pubDate']
print(category1, category2, name, low_price, high_price, avg_price, spec_info, place, unit_info,
pub_date)
sql_insert_data = """
INSERT INTO xinfadi (category1, category2, name, low_price, high_price, avg_price, spec_info, place, unit_info, pub_date)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
"""
db_cur.execute(sql_insert_data, (
category1, category2, name, low_price, high_price, avg_price, spec_info, place, unit_info, pub_date))
db_conn.commit()
except Exception as e:
print(e)
time.sleep(0.5)
return True
# 连接MySQL数据库
conn = pymysql.connect(host='localhost', user='root', password='123456', database='vegetables')
cursor = conn.cursor()
# 创建数据表
sql_create_table = """
CREATE TABLE IF NOT EXISTS xinfadi (
id INT(11) NOT NULL AUTO_INCREMENT,
category1 VARCHAR(255),
category2 VARCHAR(255),
name VARCHAR(255),
low_price FLOAT,
high_price FLOAT,
avg_price FLOAT,
spec_info VARCHAR(255),
place VARCHAR(255),
unit_info VARCHAR(255),
pub_date DATE,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
"""
cursor.execute(sql_create_table)
# 爬取并存储数据
try:
status = crawl_and_store_data(conn, cursor, 1, 20)
if status:
print("数据爬取完成!")
except Exception as e:
print(e)
# 关闭数据库连接
cursor.close()
conn.close()
注意事项与优化方向
注意事项
- 请求频率控制 :本文在异常处理中加入了
time.sleep(0.5),实际使用中可根据网站反爬规则调整请求间隔,避免过于频繁的请求导致IP被封禁。 - 编码问题 :代码开头设置
# coding=gbk,数据库表设置CHARSET=utf8,确保中文数据正常存储,避免乱码。 - 异常处理:代码中对数据解析和插入过程做了异常捕获,但可进一步细化异常类型(如数据库连接异常、请求超时异常等),提升程序鲁棒性。
- 数据库权限:确保连接MySQL的用户有足够的权限(如创建表、插入数据),避免权限不足导致操作失败。
优化方向
- 增量爬取 :当前代码爬取指定页码的全部数据,可增加按日期筛选的逻辑(利用
pubDateStartTime和pubDateEndTime参数),实现增量爬取,避免重复数据。 - 多线程/异步爬取 :对于大量数据爬取,可使用
threading多线程或aiohttp异步请求,提升爬取效率。 - 数据去重:在插入数据前增加去重逻辑(如根据农产品名称、规格、日期等字段判断),避免数据库中出现重复数据。
- 日志记录 :替换
print语句为logging模块,将爬取日志、异常信息记录到文件,方便后续排查问题。 - 配置文件化 :将数据库连接信息、爬取页码范围、请求头信息等写入配置文件(如
config.ini),提升代码的可维护性。
总结
本文通过Python实现了北京新发地农产品价格数据的爬取与MySQL存储,涵盖了网络请求、JSON解析、数据库操作等核心知识点。该方案不仅能满足基础的爬取需求,还可根据实际场景进行扩展优化,适用于农产品价格分析、市场监控等业务场景。希望本文能帮助大家掌握爬虫与数据库结合的实战技巧,也欢迎大家基于此代码进行更深入的二次开发。