• 网络触手获取天气数据存入mysql 项目


    首先这个案例不一定能直接拿来用,虽然我觉得可以但是里面肯定有一些我没考虑到的地方。

    有问题评论或者私信我: 这个案例适合我这种学生小白

    获取天气数据网址: https://lishi.tianqi.com/xianyang/202201.html

    网络触手获取天气数据代码直接就可以使用,我们只需要改动几个地方,我将改动的地方给大家注释出来:

    首先在url中:

      https://lishi.tianqi.com/xianyang/202201.html,你可以改成你们城市的名称比如  西安:

    https://lishi.tianqi.com/xian/202401.html

     通过观察1月和2月的天气数据存在的网址中发现,https://lishi.tianqi.com/xianyang/202201.html

     202201  表示2022年1月份,所以你可以推出2022年2月的网址在这块的变化应该是:202202,那十月份就应该是202210,这个地方体现在代码的

    # ('0' + str(month) if month < 10 else str(month))  这是一个三元表达式

    # 首先从  if month < 10 开始,如果month 小于10,则执行 '0' + str(month),这叫做符串拼接,形成的是一个新的字符串,如果不满足也就是 大于10则执行str(month),将month强制转化为字符串。不论满不满足也就是month < 10   符不符合小于10,都会在执行一次字符串拼接,('2022' + '0' + str(month)  或 ('2022' + str(month))

    weather_time = '2022' + ('0' + str(month) if month < 10 else str(month))

    # 这里是字符串格式化,还用到字符串拼接
    url = 'https://lishi.tianqi.com/xianyang/'+f'{weather_time}.html'

    网址的其他地方都一样:

     

     其他地方都不用管你可以直接用,我知道代码可能对有的朋友不太友好,看不懂,没关系,你先试试看能不能用。看不懂你给我发私信,我看到第一时间给大家回复。

    1. # 开始请求时间
    2. start_time = time.time()
    3. # global requests_count, start_time
    4. # # 请求完成结束时间
    5. # current_time = time.time()
    6. # elapsed_time_since_start = current_time - start_time
    7. # minute_passed = int(elapsed_time_since_start/60)
    8. # while requests_count >= minute_passed *max_reuqests_per:
    9. #
    10. # print("请求过于频繁")
    11. # #
    12. # #
    13. # requests_count +=1
    14. def getWeather(url):
    15. weather_info = []
    16. headers = {
    17. 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
    18. 'Cookie': 'lianjia_uuid=9d3277d3-58e4-440e-bade-5069cb5203a4; UM_distinctid=16ba37f7160390-05f17711c11c3e-454c0b2b-100200-16ba37f716618b; _smt_uid=5d176c66.5119839a; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2216ba37f7a942a6-0671dfdde0398a-454c0b2b-1049088-16ba37f7a95409%22%2C%22%24device_id%22%3A%2216ba37f7a942a6-0671dfdde0398a-454c0b2b-1049088-16ba37f7a95409%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%7D%7D; _ga=GA1.2.1772719071.1561816174; Hm_lvt_9152f8221cb6243a53c83b956842be8a=1561822858; _jzqa=1.2532744094467475000.1561816167.1561822858.1561870561.3; CNZZDATA1253477573=987273979-1561811144-%7C1561865554; CNZZDATA1254525948=879163647-1561815364-%7C1561869382; CNZZDATA1255633284=1986996647-1561812900-%7C1561866923; CNZZDATA1255604082=891570058-1561813905-%7C1561866148; _qzja=1.1577983579.1561816168942.1561822857520.1561870561449.1561870561449.1561870847908.0.0.0.7.3; select_city=110000; lianjia_ssid=4e1fa281-1ebf-e1c1-ac56-32b3ec83f7ca; srcid=eyJ0Ijoie1wiZGF0YVwiOlwiMzQ2MDU5ZTQ0OWY4N2RiOTE4NjQ5YmQ0ZGRlMDAyZmFhODZmNjI1ZDQyNWU0OGQ3MjE3Yzk5NzFiYTY4ODM4ZThiZDNhZjliNGU4ODM4M2M3ODZhNDNiNjM1NzMzNjQ4ODY3MWVhMWFmNzFjMDVmMDY4NWMyMTM3MjIxYjBmYzhkYWE1MzIyNzFlOGMyOWFiYmQwZjBjYjcyNmIwOWEwYTNlMTY2MDI1NjkyOTBkNjQ1ZDkwNGM5ZDhkYTIyODU0ZmQzZjhjODhlNGQ1NGRkZTA0ZTBlZDFiNmIxOTE2YmU1NTIxNzhhMGQ3Yzk0ZjQ4NDBlZWI0YjlhYzFiYmJlZjJlNDQ5MDdlNzcxMzAwMmM1ODBlZDJkNmIwZmY0NDAwYmQxNjNjZDlhNmJkNDk3NGMzOTQxNTdkYjZlMjJkYjAxYjIzNjdmYzhiNzMxZDA1MGJlNjBmNzQxMTZjNDIzNFwiLFwia2V5X2lkXCI6XCIxXCIsXCJzaWduXCI6XCIzMGJlNDJiN1wifSIsInIiOiJodHRwczovL2JqLmxpYW5qaWEuY29tL3p1ZmFuZy9yY28zMS8iLCJvcyI6IndlYiIsInYiOiIwLjEifQ=='
    19. }
    20. reponse = requests.get(url=url, headers=headers)
    21. if reponse.status_code==200:
    22. reponse.encoding = reponse.apparent_encoding
    23. # 正则表达式获取需要标题
    24. pattern = r'
      (.*?)
      \s*
      (.*?)
      \s*
      (.*?)
      \s*
      (.*?)
      '
    25. matches = re.findall(pattern, reponse.text)
    26. # 将匹配的结果转换为字典列表
    27. for match in matches[1:]:
    28. # 这里有错误
    29. date_str = match[0]
    30. # 使用split分割字符串,取第一部分
    31. date_str = date_str.split(' ')[0]
    32. #第一个 %Y-%m-%d 在 strptime 函数中起到解析的作用,将字符串 date_only 按照这种格式解释为一个 datetime 对象
    33. #第二个 %Y-%m-%d 在 strftime 方法中起到格式化的作用,将前面解析得到的 datetime 对象转换回字符串
    34. #转换回字符串 不会影响存入mysql吗 因为刚才在写入MySQL的Connect_MySQL.py 文件中Date
    35. #将日期字符串转换回 YYYY-MM-DD 格式的字符串并不会影响其存入MySQL数据库,只要数据库表结构中的对应列是日期类型(如 DATE 或 DATETIME)
    36. formatted_date = datetime.strptime(date_str, '%Y-%m-%d').strftime('%Y-%m-%d')
    37. highest_temp = float(match[1].replace('℃', ''))
    38. lowest_temp = float(match[2].replace('℃', ''))
    39. weather_data = {'日期':formatted_date , '最高温': highest_temp,'最低温': lowest_temp,
    40. '天气状况': match[3]}
    41. weather_info.append(weather_data)
    42. return weather_info
    43. # 创建一个空的DataFrame 且给上columns 名称
    44. weather_df = pd.DataFrame(columns=['日期', '最高温', '最低温', '天气状况'])
    45. for month in range(1,13):
    46. # 202302
    47. # 三元表达式 凑请求链接
    48. weather_time = '2022' + ('0' + str(month) if month < 10 else str(month))
    49. url = 'https://lishi.tianqi.com/xianyang/'+f'{weather_time}.html'
    50. # 调用函数并将结果添加到DataFrame中
    51. monthly_weather = getWeather(url)
    52. monthly_weather_df = pd.DataFrame(monthly_weather)
    53. weather_df = pd.concat([weather_df, monthly_weather_df])
    54. # response_time = time.time() - start_time
    55. # time.sleep(min(response_time, 5) + random.uniform(0.5, 1))
    56. print(weather_df)

     存入数据库代码:

    需要注意的是(都输入你的):

    1. # 定义数据库连接参数
    2. 5 db_config = {
    3. 6 'host': 'your_host', # 数据库地址
    4. 7 'port': your_port, # 数据库端口
    5. 8 'user': 'your_username', # 数据库用户名
    6. 9 'password': 'your_password', # 数据库密码
    7. 10 'database': 'your_database', # 数据库名称
    8. 11 }
    9. 12
    10. 13# 创建数据库引擎
    11. engine = create_engine(f'mysql+pymysql://{db_config["user"]}:{db_config["password"]}@{db_config["host"]}:{db_config["port"]}/{db_config["database"]}')

    还有必须要手动在你的本地数据库中创建一个名为  “weather" 的数据库

     如果忘记了没关系:

    我告诉大家一个方法如何找到这些信息,前提是安装了一些操作数据库的可视化软件任何都行,我用的是sqlyong。

    第一步:打开可视化工具

    第二步:

     

     如果出现连接失败,我只能解决密码忘记问题,其他问题其实应该可以我没遇到过,例如端口被占用,数据库地址不对,这在安装数据库的时候就要注意,怎么弄,也就是大家都怎么写你就怎么写,不要搞一些复杂的到时候就忘记了。

    mysql  数据库密码忘记,重置密码网址:

    http://t.csdnimg.cn/9m1ax     作者: csdn博主 小达学加瓦  

    连接、测试、写入数据库代码:

    (不知道没关系,这个代码包含了检测是否存在表,不存在创建表,数据是否写入成功不成功抛出错误),只要你把我刚说前面那些写对,就应该直接能用

    1. from sqlalchemy import create_engine, MetaData, Table, Column, Float, String, Date
    2. from sqlalchemy.exc import OperationalError
    3. from sqlalchemy import inspect
    4. # 定义数据库连接参数
    5. db_config = {
    6. 'host': '127.0.0.1', # 数据库地址
    7. 'port': 3307, # 数据库端口
    8. 'user': 'root', # 数据库用户名
    9. 'password': '123456', # 数据库密码
    10. 'database': 'weather', # 数据库名称
    11. }
    12. # 创建数据库引擎
    13. engine = create_engine(f'mysql+pymysql://{db_config["user"]}:{db_config["password"]}@{db_config["host"]}:{db_config["port"]}/{db_config["database"]}')
    14. # 测试数据库连接是否成功
    15. try:
    16. connection = engine.connect()
    17. print("数据库连接成功!")
    18. except Exception as e:
    19. print(f"数据库连接失败:{str(e)}")
    20. # 创建表(如果不存在)
    21. metadata = MetaData()
    22. table_name = 'weather_data'
    23. table_columns = [
    24. Column('日期', Date),
    25. Column('最高温', Float),
    26. Column('最低温', Float),
    27. Column('天气状况', String(255)),
    28. ]
    29. weather_table = Table(table_name, metadata, *table_columns, extend_existing=True)
    30. # 检查表是否存在,如果不存在则创建表
    31. inspector = inspect(engine)
    32. if not inspector.has_table(table_name):
    33. # 注意这里需要传递 engine 到 create_all 方法中
    34. metadata.create_all(bind=engine)
    35. # 检查表是否存在,如果不存在则创建表
    36. try:
    37. metadata.create_all(engine)
    38. except OperationalError as oe:
    39. if "already exists" in str(oe): # 如果表已存在则忽略错误
    40. print("cunza")
    41. else:
    42. raise oe
    43. print("表 'weather_data' 已经检查并创建完毕(如有必要)")
    44. # 将数据写入数据库
    45. if weather_df is not None and not weather_df.empty:
    46. weather_df.to_sql(name=table_name, con=engine, if_exists='append', index=False, dtype={
    47. '日期': Date,
    48. '最高温': Float,
    49. '最低温': Float,
    50. '天气状况': String(255),
    51. })
    52. print("数据已成功写入 'weather_data' 表.")
    53. else:
    54. print("未找到待写入数据库的数据.")

    主函数:运行这个大程序:

    1. from my_project.tianqi.tianqi import get_weather_data
    2. from my_project.database.Connect_MySQL import save_to_database
    3. def main():
    4. weather_df = get_weather_data()
    5. save_to_database(weather_df)
    6. if __name__ == "__main__":
    7. main()

    文件夹以文件架构:这是模块(包或文件夹的创建位置很重要) 

     完整程序代码:

    1. # 天气文件 使用前请先按照文件夹的架构层级创建文件夹和文件 ,以下三个python 都是一样的要求
    2. #file--tianqi.py
    3. import random
    4. import time
    5. import re
    6. import pandas as pd
    7. from datetime import datetime
    8. import requests
    9. from lxml import etree
    10. def get_weather_data():
    11. # 设置每分钟允许的最大请求数量
    12. max_reuqests_per = 20
    13. requests_count = 0
    14. # 开始请求时间
    15. start_time = time.time()
    16. # global requests_count, start_time
    17. # # 请求完成结束时间
    18. # current_time = time.time()
    19. # elapsed_time_since_start = current_time - start_time
    20. # minute_passed = int(elapsed_time_since_start/60)
    21. # while requests_count >= minute_passed *max_reuqests_per:
    22. #
    23. # print("请求过于频繁")
    24. # #
    25. # #
    26. # requests_count +=1
    27. def getWeather(url):
    28. weather_info = []
    29. headers = {
    30. 'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36',
    31. 'Cookie': 'lianjia_uuid=9d3277d3-58e4-440e-bade-5069cb5203a4; UM_distinctid=16ba37f7160390-05f17711c11c3e-454c0b2b-100200-16ba37f716618b; _smt_uid=5d176c66.5119839a; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2216ba37f7a942a6-0671dfdde0398a-454c0b2b-1049088-16ba37f7a95409%22%2C%22%24device_id%22%3A%2216ba37f7a942a6-0671dfdde0398a-454c0b2b-1049088-16ba37f7a95409%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%7D%7D; _ga=GA1.2.1772719071.1561816174; Hm_lvt_9152f8221cb6243a53c83b956842be8a=1561822858; _jzqa=1.2532744094467475000.1561816167.1561822858.1561870561.3; CNZZDATA1253477573=987273979-1561811144-%7C1561865554; CNZZDATA1254525948=879163647-1561815364-%7C1561869382; CNZZDATA1255633284=1986996647-1561812900-%7C1561866923; CNZZDATA1255604082=891570058-1561813905-%7C1561866148; _qzja=1.1577983579.1561816168942.1561822857520.1561870561449.1561870561449.1561870847908.0.0.0.7.3; select_city=110000; lianjia_ssid=4e1fa281-1ebf-e1c1-ac56-32b3ec83f7ca; srcid=eyJ0Ijoie1wiZGF0YVwiOlwiMzQ2MDU5ZTQ0OWY4N2RiOTE4NjQ5YmQ0ZGRlMDAyZmFhODZmNjI1ZDQyNWU0OGQ3MjE3Yzk5NzFiYTY4ODM4ZThiZDNhZjliNGU4ODM4M2M3ODZhNDNiNjM1NzMzNjQ4ODY3MWVhMWFmNzFjMDVmMDY4NWMyMTM3MjIxYjBmYzhkYWE1MzIyNzFlOGMyOWFiYmQwZjBjYjcyNmIwOWEwYTNlMTY2MDI1NjkyOTBkNjQ1ZDkwNGM5ZDhkYTIyODU0ZmQzZjhjODhlNGQ1NGRkZTA0ZTBlZDFiNmIxOTE2YmU1NTIxNzhhMGQ3Yzk0ZjQ4NDBlZWI0YjlhYzFiYmJlZjJlNDQ5MDdlNzcxMzAwMmM1ODBlZDJkNmIwZmY0NDAwYmQxNjNjZDlhNmJkNDk3NGMzOTQxNTdkYjZlMjJkYjAxYjIzNjdmYzhiNzMxZDA1MGJlNjBmNzQxMTZjNDIzNFwiLFwia2V5X2lkXCI6XCIxXCIsXCJzaWduXCI6XCIzMGJlNDJiN1wifSIsInIiOiJodHRwczovL2JqLmxpYW5qaWEuY29tL3p1ZmFuZy9yY28zMS8iLCJvcyI6IndlYiIsInYiOiIwLjEifQ=='
    32. }
    33. reponse = requests.get(url=url, headers=headers)
    34. if reponse.status_code==200:
    35. reponse.encoding = reponse.apparent_encoding
    36. # 正则表达式获取需要标题
    37. pattern = r'
      (.*?)
      \s*
      (.*?)
      \s*
      (.*?)
      \s*
      (.*?)
      '
    38. matches = re.findall(pattern, reponse.text)
    39. # 将匹配的结果转换为字典列表
    40. for match in matches[1:]:
    41. # 这里有错误
    42. date_str = match[0]
    43. # 使用split分割字符串,取第一部分
    44. date_str = date_str.split(' ')[0]
    45. #第一个 %Y-%m-%d 在 strptime 函数中起到解析的作用,将字符串 date_only 按照这种格式解释为一个 datetime 对象
    46. #第二个 %Y-%m-%d 在 strftime 方法中起到格式化的作用,将前面解析得到的 datetime 对象转换回字符串
    47. #转换回字符串 不会影响存入mysql吗 因为刚才在写入MySQL的Connect_MySQL.py 文件中Date
    48. #将日期字符串转换回 YYYY-MM-DD 格式的字符串并不会影响其存入MySQL数据库,只要数据库表结构中的对应列是日期类型(如 DATE 或 DATETIME)
    49. formatted_date = datetime.strptime(date_str, '%Y-%m-%d').strftime('%Y-%m-%d')
    50. highest_temp = float(match[1].replace('℃', ''))
    51. lowest_temp = float(match[2].replace('℃', ''))
    52. weather_data = {'日期':formatted_date , '最高温': highest_temp,'最低温': lowest_temp,
    53. '天气状况': match[3]}
    54. weather_info.append(weather_data)
    55. return weather_info
    56. # 创建一个空的DataFrame 且给上columns 名称
    57. weather_df = pd.DataFrame(columns=['日期', '最高温', '最低温', '天气状况'])
    58. for month in range(1,13):
    59. # 202302
    60. # 三元表达式 凑请求链接
    61. weather_time = '2022' + ('0' + str(month) if month < 10 else str(month))
    62. url = 'https://lishi.tianqi.com/xianyang/'+f'{weather_time}.html'
    63. # 调用函数并将结果添加到DataFrame中
    64. monthly_weather = getWeather(url)
    65. monthly_weather_df = pd.DataFrame(monthly_weather)
    66. weather_df = pd.concat([weather_df, monthly_weather_df])
    67. # response_time = time.time() - start_time
    68. # time.sleep(min(response_time, 5) + random.uniform(0.5, 1))
    69. print(weather_df)
    70. return weather_df
    71. get_weather_data()

     数据库文件:

    1. # file--Coonect_MySQl
    2. import pymysql
    3. from sqlalchemy import create_engine, MetaData, Table, Column, Float, String, Date
    4. from sqlalchemy.exc import OperationalError
    5. from sqlalchemy import inspect
    6. def save_to_database(weather_df):
    7. # 定义数据库连接参数
    8. db_config = {
    9. 'host': '127.0.0.1', # 数据库地址
    10. 'port': 3307, # 数据库端口
    11. 'user': 'root', # 数据库用户名
    12. 'password': '123456', # 数据库密码
    13. 'database': 'weather', # 数据库名称
    14. }
    15. # 创建数据库引擎
    16. engine = create_engine(f'mysql+pymysql://{db_config["user"]}:{db_config["password"]}@{db_config["host"]}:{db_config["port"]}/{db_config["database"]}')
    17. # 测试数据库连接是否成功
    18. try:
    19. connection = engine.connect()
    20. print("数据库连接成功!")
    21. except Exception as e:
    22. print(f"数据库连接失败:{str(e)}")
    23. # 创建表(如果不存在)
    24. metadata = MetaData()
    25. table_name = 'weather_data'
    26. table_columns = [
    27. Column('日期', Date),
    28. Column('最高温', Float),
    29. Column('最低温', Float),
    30. Column('天气状况', String(255)),
    31. ]
    32. weather_table = Table(table_name, metadata, *table_columns, extend_existing=True)
    33. # 检查表是否存在,如果不存在则创建表
    34. inspector = inspect(engine)
    35. if not inspector.has_table(table_name):
    36. # 注意这里需要传递 engine 到 create_all 方法中
    37. metadata.create_all(bind=engine)
    38. # 检查表是否存在,如果不存在则创建表
    39. try:
    40. metadata.create_all(engine)
    41. except OperationalError as oe:
    42. if "already exists" in str(oe): # 如果表已存在则忽略错误
    43. print("cunza")
    44. else:
    45. raise oe
    46. print("表 'weather_data' 已经检查并创建完毕(如有必要)")
    47. # 将数据写入数据库
    48. if weather_df is not None and not weather_df.empty:
    49. weather_df.to_sql(name=table_name, con=engine, if_exists='append', index=False, dtype={
    50. '日期': Date,
    51. '最高温': Float,
    52. '最低温': Float,
    53. '天气状况': String(255),
    54. })
    55. print("数据已成功写入 'weather_data' 表.")
    56. else:
    57. print("未找到待写入数据库的数据.")

     主文件充当运行程序运行文件

    1. from my_project.tianqi.tianqi import get_weather_data
    2. from my_project.database.Connect_MySQL import save_to_database
    3. def main():
    4. weather_df = get_weather_data()
    5. save_to_database(weather_df)
    6. if __name__ == "__main__":
    7. main()

    这是效果:


    这里的很多技术难点我都是问的大模型,他们很聪明,完全能应付一些简单日常的问题。

    希望帮到大家,祝大家安康 

  • 相关阅读:
    【ES6】js 中class的extends、super关键字用法和避坑点
    Paper - Neural Discrete Representation Learning (VQ-VAE) 论文简读
    【MySQL高级】MySQL的存储引擎
    电脑翻译软件-大家都觉得好用的免费电脑翻译软件
    c语言中常用的操作符,字符串的结束字符\0
    BLUE引擎变量数据分析
    43Nginx+Tomcat负载均衡与动静分离
    时间空间复杂度
    机器学习---拉格朗日乘子法、Huber Loss、极大似然函数取对数的原因
    ZooKeeper
  • 原文地址:https://blog.csdn.net/weixin_59131972/article/details/136589112