使用爬虫爬取天气历史数据(https://lishi.tianqi.com/)

          目标:获取历史天气查询|历史天气预报查询|历史气温查询|过去天气查询_历史天气查询网 这个页面中所有城市在2021.1~2021.7的历史天气数据

一、获取爬虫头:

  

import requests
from bs4 import BeautifulSoup
from fake_useragent import UserAgent
import os
import random
from bs4 import BeautifulSoup
import time
import socket
import re

import pandas as pd
import os

proxies_ = {
  'http': "你的proxy代理",
  'https':"你的proxy代理",
}

def get_header():
    headers = {
    'User-Agent': ua.random
    }
    
    return headers

from fake_useragent import UserAgent
 
ua = UserAgent(path='./fake_useragent.json')  #使用了本地的user_agent库。fake_useragent.json文件网上有。
 
print(ua.chrome)

        二、获取所有城市名:

target = "http://lishi.tianqi.com/"
req = requests.get(url=target, headers=get_header(),timeout=60)

soup = BeautifulSoup(req.text, 'html.parser')   


import re
#根据数据结果设置正则匹配方式
get_city_pinyin  = """(?<=href=").*(?=/index.html)"""
get_city_chinese = """(?<=>).*(?=</a>)"""

get_city_pinyin_pattern = re.compile(get_city_pinyin)
get_city_chinese_pattern = re.compile(get_city_chinese)


#返回拼音形式的城市名列表和他们的中文名称
def get_citys(soup):
    pinyin_list = []
    chinese_name_list = []
    data_table =  soup.find_all('table')[0]
    city_columns = data_table.find_all('a')
    for data_item in city_columns:
        data_item = str(data_item)
        pinyin = get_city_pinyin_pattern.findall(data_item)
        if (len(pinyin) == 0): continue
        pinyin = pinyin[0]
        chinese_name = get_city_chinese_pattern.findall(data_item)[0]
        pinyin_list.append(pinyin)
        chinese_name_list.append(chinese_name)
    return [pinyin_list, chinese_name_list]


res = get_citys(soup)

三、获取各个城市的历史天气数据:

#获取的某个月的数据
def get_cur_month_data(soup):
    d = soup.find_all("li")
    month_data_list = []
    for item1 in d:
        item2 = item1.find_all("div")
        if ("""<div class="th200">""" in str(item2)):
            day_list = []
            for item in item2:
                item = str(item)
                res = get_day_res_pattern.findall(item)[0]
                day_list.append(res)
            month_data_list.append(day_list)
    return month_data_list

四、建立循环:

pinyin_list = res[0]  #这里是res是城市列表名。由res = get_citys(soup)得到
chinese_name_list = res[1]

city_pinyin_chinese = dict()

for i in range(3, len(pinyin_list)):  #朱日和苏右旗,跳过
    pinyin = pinyin_list[i]
    chinese = chinese_name_list[i]
    city_pinyin_chinese[chinese] = pinyin

pinyin_list = pinyin_list[2:]
random.shuffle(pinyin_list)  #打乱顺序



def get_now_time():
    return time.strftime("%Y-%m-%d %H:%M:%S",time.localtime(time.time()))



import time

#控制爬虫频率
def random_sleep():
    A = 1.72
    B = 5.19
    a = random.uniform(A,B)
    C = 3#随机数的精度round(数值,精度)
    res = round(a,C)
    time.sleep(res)

import time
#长睡
def long_sleep():
    A = 32.74
    B = 64.75
    a = random.uniform(A,B)
    C = 3#随机数的精度round(数值,精度)
    res = round(a,C)
    time.sleep(res)

import pickle
def save_variable(v,filename):
    f=open(filename,'wb')
    pickle.dump(v,f)
    f.close()


def load_variable(filename):
    f=open(filename,'rb')
    r=pickle.load(f)
    f.close()
    return r


processed_city_month = set()   #记录已经爬取的城市名和月份,以便重跑时跳过
error_city_month = set()       #记录出错的城市名和月份,以便重跑




get_day_res="""(?<=">).*(?=</div>)"""
get_day_res_pattern = re.compile(get_day_res)


month_list = ["20210" + str(i) for i in range(1, 8)] #2021.1~2021.7

city_datas = dict()

c = 0
print ("爬虫启动时间=", get_now_time())
start_time = time.time()

for i in range(0, len(pinyin_list)):
    name = pinyin_list[i]
    
    if name not in city_datas:
        city_datas[name] = dict()
        
    for month in month_list:
        query_item = str(name) + "|" + str(month)
        if (query_item in processed_city_month):continue
        target = """https://lishi.tianqi.com/""" + str(name) + """/"""+str(month) + ".html"
#         print (target)
        try:
            req = requests.get(url=target,headers=get_header(),timeout=60,proxies=proxies_,verify=False)
        except Exception as e:
            print (query_item, e)
            error_city_month.add(query_item)
            continue
        soup = BeautifulSoup(req.text, 'html.parser')
        month_data_list = get_cur_month_data(soup)
        city_datas[name][month] = month_data_list 
        processed_city_month.add(query_item)
        c += 1
        if (c % 10 == 0):
            cur_time = time.time()
            remaining_time = (len(pinyin_list) * len(month_list) - c) * (cur_time - start_time) / c
            remaining_minute = round(remaining_time / 60, 5)
            print (len(city_datas), remaining_minute)
        random_sleep()
        if (c % 1001 == 0):  #适当长睡
            long_sleep()
        if (c % 5000 == 0):   #定时保存
            index = int(c / 5000)
            file_name = "city_datas_"+ str(index) + ".pkl"
            save_variable(city_datas,file_name)


file_name = "city_datas_"+ str("all") + ".pkl"
save_variable(city_datas,file_name)






  • 4
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个比较完整的爬虫项目,需要考虑很多方面。下面是一个大致的思路: 1. 创建一个 Scrapy 项目,定义好 Item 和 Spider。 2. 在 Spider 中定义初始页面和翻页的规则。首先要爬取的是 https://lishi.tianqi.com/beijing/index.html 这个页面,然后在该页面中找到“选择月份”的链接,用它来构造翻页规则,例如: ```python start_urls = ["https://lishi.tianqi.com/beijing/index.html"] def parse(self, response): # 获取“选择月份”的链接 month_links = response.css('.tqtongji2 .tqmonth a::attr(href)').getall() for link in month_links: yield scrapy.Request(url=link, callback=self.parse_month_page) ``` 在 `parse_month_page` 方法中,可以解析每个月份的页面,并把数据存入 CSV 文件和 MySQL 数据库中。 3. 在 Item 中定义需要爬取的数据字段,例如日期、温度、气压、风力等: ```python class WeatherItem(scrapy.Item): date = scrapy.Field() temperature = scrapy.Field() pressure = scrapy.Field() wind = scrapy.Field() ``` 4. 在 Spider 中解析每个月份的页面,获取数据并存入 CSV 文件和 MySQL 数据库中。首先要找到每个月份页面中的天气数据表格,然后循环解析每一行数据: ```python def parse_month_page(self, response): # 找到天气数据表格 table = response.css('.tqtongji1 table')[1] rows = table.css('tr') for row in rows[1:]: # 解析每一行数据 item = WeatherItem() item['date'] = row.css('td:nth-child(1)::text').get() item['temperature'] = row.css('td:nth-child(2)::text').get() item['pressure'] = row.css('td:nth-child(3)::text').get() item['wind'] = row.css('td:nth-child(4)::text').get() yield item ``` 5. 在 Spider 中定义数据存储管道,将数据存入 CSV 文件和 MySQL 数据库中: ```python class WeatherPipeline: def open_spider(self, spider): self.file = open('weather.csv', 'w', encoding='utf-8', newline='') self.writer = csv.writer(self.file) self.writer.writerow(['日期', '温度', '气压', '风力']) self.conn = pymysql.connect(host='localhost', user='root', password='123456', db='test', charset='utf8') self.cursor = self.conn.cursor() def close_spider(self, spider): self.file.close() self.conn.close() def process_item(self, item, spider): # 写入 CSV 文件 self.writer.writerow([item['date'], item['temperature'], item['pressure'], item['wind']]) # 存入 MySQL 数据库 sql = "INSERT INTO weather(date, temperature, pressure, wind) VALUES (%s, %s, %s, %s)" values = (item['date'], item['temperature'], item['pressure'], item['wind']) self.cursor.execute(sql, values) self.conn.commit() return item ``` 6. 在 Spider 中定义翻页的规则。根据“选择月份”的链接构造出每个月份页面的 URL,例如 https://lishi.tianqi.com/beijing/202208.html,https://lishi.tianqi.com/beijing/202209.html,https://lishi.tianqi.com/beijing/202210.html 等等,可以使用 `scrapy.Request` 方法来构造请求: ```python def parse(self, response): # 获取“选择月份”的链接 month_links = response.css('.tqtongji2 .tqmonth a::attr(href)').getall() for link in month_links: # 构造每个月份页面的 URL url = response.urljoin(link.replace('.html', '')) for i in range(1, 32): # 构造每一天的 URL day_url = url + f'{i:02d}.html' yield scrapy.Request(url=day_url, callback=self.parse_day_page) ``` 在 `parse_day_page` 方法中,可以解析每一天的页面,并把数据存入 CSV 文件和 MySQL 数据库中。 以上就是一个大致的思路,具体的实现细节还需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值