首页 > 其他分享 >爬虫实战:从外地天气到美食推荐,探索干饭人的世界

爬虫实战:从外地天气到美食推荐,探索干饭人的世界

时间:2024-03-18 09:35:18浏览次数:26  
标签:city text tag 爬虫 html 美食 print 干饭 find

今天是第二堂课,我们将继续学习爬虫技术。在上一节课中,我们已经学会了如何爬取干饭教程。正如鲁迅所说(我没说过),当地吃完饭就去外地吃,这启发了我去爬取城市天气信息,并顺便了解当地美食。这个想法永远是干饭人的灵魂所在。

今天我们的目标是学习如何爬取城市天气信息,因为要计划去哪里玩耍,首先得了解天气情况。虽然我们的手机已经装有许多免费天气软件,但是也不妨碍我们学习。

在我们开始学习爬虫技术之前,首先需要找到一个容易爬取数据的天气网站。并不要求特定网站,只要易于爬取的网站即可。毕竟我们目前并不需要爬取特定网站来抢票或抢购商品,我们的主要目的是学习爬虫技术。

天气爬虫

在进行爬虫操作时,如果不确定一个网站是否易于爬取,可以先尝试输入该网站的首页地址,查看能否成功解析出HTML网页。如果解析出来的页面与实际浏览的页面一致,那么说明该网站可能没有设置反爬虫机制;反之,如果解析出来的页面与实际不同,那么该网站很可能设置了反爬虫措施。在学习阶段,建议选择较为容易爬取的网站进行练习,避免过早挑战难度过大的网站。

好的,废话不多说,我们现在就开始抓取该网站上的所有城市信息。

城市列表

天气信息肯定与城市相关,因此几乎每个天气网站都会有城市列表。让我们先来抓取这些城市列表并保存起来,以备后续使用。以下是相应的代码:

# 导入urllib库的urlopen函数
from urllib.request import urlopen,Request
# 导入BeautifulSoup
from bs4 import BeautifulSoup as bf

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0'}
req = Request("https://www.tianqi.com/chinacity.html",headers=headers)
# 发出请求,获取html
# 获取的html内容是字节,将其转化为字符串
html = urlopen(req)
html_text = bytes.decode(html.read())
obj = bf(html_text,'html.parser')
# 使用find_all函数获取所有图片的信息
province_tags = obj.find_all('h2')
for province_tag in province_tags:
    province_name = province_tag.text.strip()
    cities = []
    print(province_name)
    next_sibling = province_tag.find_next_sibling()
    city_tags = next_sibling.find_all('a')
    for city_tag in city_tags:
        city_name = city_tag.text.strip()
        cities.append(city_name)
        print(city_name)

在上述操作中,主要的步骤是从城市地址页面中获取信息,对其进行解析以获取省份和城市之间的对应关系。目前仅仅进行了简单的打印输出。

城市天气

在获取城市信息之后,接下来的步骤是根据城市信息获取天气信息。在这里,我们仅考虑直辖市的天气情况,而省份的天气信息获取相比直辖市多了一步省份的跳转。我们暂时不进行省份天气信息的演示。现在,让我们一起来看一下代码:

# 导入urllib库的urlopen函数
from urllib.request import urlopen,Request
# 导入BeautifulSoup
from bs4 import BeautifulSoup as bf

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0'}
req = Request(f"https://www.tianqi.com/beijing/",headers=headers)
# 发出请求,获取html
# 获取的html内容是字节,将其转化为字符串
html = urlopen(req)
html_text = bytes.decode(html.read())
obj = bf(html_text,'html.parser')
city_tags = obj.find_all('div',class_='mainWeather')
for city_tag in city_tags:
    a_tags = city_tag.find_all('a', class_=lambda value: value != 'd15')
    for a_tag in a_tags:
        title = a_tag.get('title')
        print(title)
foods = obj.find_all('ul',class_='paihang_good_food')
for food in foods:
    a_tags = food.find_all('a')
    for a_tag in a_tags:
        href = a_tag.get('href')
        print(href)
        title = a_tag.get('title')
        print(title)
weather_info = obj.find_all('dl', class_='weather_info')
for info in weather_info:
    city_name = info.find('h1').text
    date = info.find('dd', class_='week').text
    temperature = info.find('p', class_='now').text
    humidity = info.find('dd', class_='shidu').text
    air_quality = info.find('dd', class_='kongqi').h5.text
    print(f"地点:{city_name}")
    print(f"时间:{date}")
    print(f"当前温度:{temperature}")
    print(humidity)
    print(air_quality)   

以上代码不仅仅把天气解析出来,而且将当前地址的天气和各个城区 的天气以及当地美食都解析了出来。当地美食因为链接是变动的,所以将链接和美食做了响应的映射关系保存。

城市美食

在确定天气适宜的情况下,我们通常都会想了解当地有哪些特色美食,毕竟不能总是吃快餐,特色美食才是我们吃货的灵魂所在。

以下是一个示例代码:

# 导入urllib库的urlopen函数
from urllib.request import urlopen,Request
# 导入BeautifulSoup
from bs4 import BeautifulSoup as bf

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0'}
req = Request(f"https://www.tianqi.com/meishi/1737.html",headers=headers)
# 发出请求,获取html
# 获取的html内容是字节,将其转化为字符串
html = urlopen(req)
html_text = bytes.decode(html.read())
obj = bf(html_text,'html.parser')
span_tag = obj.find('span', class_='traffic')
text_content = ''.join(span_tag.stripped_strings)
print(text_content)

在这里,我主要解析了当前美食推荐的原因。实际上,链接应该与之前解析的天气信息相关联,但为了演示方便,我在示例代码中使用了固定值。

包装一下

将以上内容单独制作成小案例确实是一种有效的方式,但将其整合成一个简单的小应用则更具实用性,因为这样可以实现更灵活的交互。让我们一起来看一下最终的代码:

# 导入urllib库的urlopen函数
from urllib.request import urlopen,Request
import urllib,string
# 导入BeautifulSoup
from bs4 import BeautifulSoup as bf
from random import choice,sample
from colorama import init
from os import system
from termcolor import colored
from readchar import  readkey
from xpinyin import Pinyin

p = Pinyin()

city_province_mapping = []

province_sub_weather = []

good_foods = []
FGS = ['green', 'yellow', 'blue', 'cyan', 'magenta', 'red']

def clear():
    system("CLS")

def get_city_province_mapping():
    print(colored('开始搜索城市',choice(FGS)))
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0'}
    req = Request("https://www.tianqi.com/chinacity.html",headers=headers)
    # 发出请求,获取html
    # 获取的html内容是字节,将其转化为字符串
    html = urlopen(req)
    html_text = bytes.decode(html.read())
    obj = bf(html_text,'html.parser')
    # 使用find_all函数获取所有图片的信息
    province_tags = obj.find_all('h2')
    for province_tag in province_tags:
        province_name = province_tag.text.strip()
        cities = []

        next_sibling = province_tag.find_next_sibling()
        city_tags = next_sibling.find_all('a')
        for city_tag in city_tags:
            city_name = city_tag.text.strip()
            cities.append(city_name)

        city_province_mapping.append((province_name,cities))


def get_province_weather(province):
    print(colored(f'已选择:{province}',choice(FGS)))
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0'}
    req = Request(f"https://www.tianqi.com/{province}/",headers=headers)
    # 发出请求,获取html
    # 获取的html内容是字节,将其转化为字符串
    html = urlopen(req)
    html_text = bytes.decode(html.read())
    obj = bf(html_text,'html.parser')
    city_tags = obj.find_all('div',class_='mainWeather')
    # city_tags = obj.find_all('ul',class_='raweather760')
    province_sub_weather.clear()
    print(colored('解析主要城市中',choice(FGS)))
    for city_tag in city_tags:
        a_tags = city_tag.find_all('a', class_=lambda value: value != 'd15')
        for a_tag in a_tags:
            title = a_tag.get('title')
            province_sub_weather.append(title)
    foods = obj.find_all('ul',class_='paihang_good_food')
    print(colored('解析热搜美食中',choice(FGS)))
    for food in foods:
        a_tags = food.find_all('a')
        for a_tag in a_tags:
            href = a_tag.get('href')
            title = a_tag.get('title')
            good_foods.append((href, title))
    weather_info = obj.find_all('dl', class_='weather_info')
    print(colored('解析完毕',choice(FGS)))
    for info in weather_info:
        city_name = info.find('h1').text
        date = info.find('dd', class_='week').text
        temperature = info.find('p', class_='now').text
        humidity = info.find('dd', class_='shidu').text
        air_quality = info.find('dd', class_='kongqi').h5.text

        print(colored(f"地点:{city_name}",choice(FGS)))
        print(colored(f"时间:{date}",choice(FGS)))
        print(colored(f"当前温度:{temperature}",choice(FGS)))
        print(colored(humidity,choice(FGS)))
        print(colored(air_quality,choice(FGS)))   
def search_food(link):
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36 Edg/122.0.0.0'}
    req = Request(f"https://www.tianqi.com{link}",headers=headers)
    # 发出请求,获取html
    # 获取的html内容是字节,将其转化为字符串
    html = urlopen(req)
    html_text = bytes.decode(html.read())
    obj = bf(html_text,'html.parser')
    span_tag = obj.find('span', class_='traffic')
    text_content = ''.join(span_tag.stripped_strings)
    print(colored(text_content,choice(FGS)))

def print_menu():
    for i in range(0, 4, 3):
        names = [f'{i + j}:{city_province_mapping[i + j][0]}' for j in range(3) if i + j < 4]
        print(colored('\t\t'.join(names),choice(FGS)))

def print_food():
    if not good_foods:
        print(colored('请选择城市,才可查看',choice(FGS)))
        return
    for i in range(0, len(good_foods), 3):
        names = [f'{i + j}:{good_foods[i + j][1]}' for j in range(3) if i + j < len(good_foods)]
        print(colored('\t\t'.join(names),choice(FGS)))

def print_hot(weather):
    if not weather:
        print(colored('请选择城市,才可查看',choice(FGS)))
        return
    for i in range(0,len(weather), 3):
        names = [f'{i + j}:{weather[i + j]}' for j in range(3) if i + j < len(weather)]
        print(colored('\t\t'.join(names),choice(FGS)))

get_city_province_mapping()

# get_province_weather('beijing')
# search_food(good_foods[1][0])
init() ## 命令行输出彩色文字
print(colored('已搜索完毕!',choice(FGS)))
print(colored('m:返回首页',choice(FGS)))
print(colored('h:查看当前城区天气',choice(FGS)))
print(colored('f:查看当地美食',choice(FGS)))
print(colored('q:退出天气',choice(FGS)))
my_key = ['q','m','c','h','f']
while True:
    while True:
        move = readkey()
        if move in my_key:
            break
    if move == 'q': ## 键盘‘Q’是退出
        break 
    if move == 'c': ## 键盘‘C’是清空控制台
        clear()
    if move == 'h':  
        print_hot(province_sub_weather)
    if move == 'f':  
        print_food()
        num = int(input('请输入美食编号:=====>'))
        if num <= len(good_foods):
            search_food(good_foods[num][0])
    if move == 'm':
        print_menu()
        num = int(input('请输入城市编号:=====>'))
        if num <= len(city_province_mapping):
            pinyin_without_tone = p.get_pinyin(city_province_mapping[num][0],'')
            get_province_weather(pinyin_without_tone)

按照我的习惯,我通常喜欢在控制台中进行打印输出,这样可以避免不必要的UI依赖。虽然整个过程并不算太复杂,但解析数据确实需要花费一些时间。尽管如此,还是成功完成了天气信息的爬取任务。

总结

在今天的学习中,所涉及的知识点基本延续了上一次的内容,并没有太多新的拓展。主要是对网页进行解析,提取信息并保存,最后根据这些信息来动态改变链接地址,最终完成了一个简单的与用户交互的演示项目。我希望你也能跟着动手实践,尽管这个过程可能会有些痛苦,不过虽然并没有给你的技术水平带来实质性提升,但至少可以拓展你的技术广度。

标签:city,text,tag,爬虫,html,美食,print,干饭,find
From: https://www.cnblogs.com/guoxiaoyu/p/18067058

相关文章

  • 写了个简单爬虫,分析 Boss 直聘自动驾驶岗位
    两年前,朋友想知道Boss直聘上关于自动驾驶的岗位有哪些,于是,笔者写了一个简单的爬虫crawler-boss,将岗位的信息收集起来。这篇文章,笔者想分享爬虫crawler-boss的设计思路。1基本原理Selenium+chromedriver对于很多动态渲染的网页而言,想要抓取它的数据,就需要对网页的J......
  • 爬虫实战爬取图片
        最近喜欢存一些图片来当住头像或者背景图,接下来我们爬一下某网站的图片1.打开网站    1.1按f12点击network然后刷新一下2.双击一下3.这时候我们就可以写代码了把基础的先写上importrequestsproxy={'http':'122.9.101.6:8888'}h......
  • 用python写网络爬虫:3.urllib库进一步的使用方法
    文章目录异常处理URLErrorHTTPError设置超时时间链接的解析、构造、合并urlparse方法urlsplit方法urljoin方法urlencode方法parse_qs方法quote方法Robots协议Robots协议的结构解析协议参考书籍在上一篇文章:用python写网络爬虫:2.urllib库的基本用法已经介绍了如......
  • 全栈的自我修养 ———— python爬虫爬取斗破苍穹小说并保存到文档里!看完保证会灵活使
    如果赶时间请直接看第四大步中的源码,好好看完这篇博客,这里保证大家以后彻底搞懂获得一个网站怎么来爬取!!!!一、准备二、选入合适的爬取的目标1、如何看出网站做了反爬2、合适的网站三、理思路1、选择合适的页面2、选择合适的元素三、爬取1、获取所有章节的链接获取网站上......
  • macos selenium msedgedriver 浏览器驱动 爬虫
    MacOSSelenium跨浏览器环境搭建在macOS上使用Selenium启动新版Edge的方式如下。macOS版本:10.15.5Edge版本:83.0.478.58下载83版本对应的新版Edge驱动:https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/#downloads解压并移动到/usr/loca......
  • python爬虫的一些代码
    你好,欢迎查看我的第5个笔记。这是本人为了保存一些代码而写的博客,由于精力实在有限,无法从头开始介绍爬虫相关的知识故仅仅罗列了几段代码案例 1.编写url管理器classUrlManager():"""url管理器罢了"""def__init__(self):self.new_urls=set()......
  • <爬虫部署,进阶Docker>----第二章 安装Docker
    前言:安装docker---本章是只针对windows的Docker! 如果你需要你就往下看,不需要就换频道~正文:1.安装Docker前配置a.开启虚拟化功能(VT)  -如果你电脑有这个(虚拟化已启用)        直接跳过这一步;如果没有,那你就去对照自己电脑开启虚拟化; 相关链......
  • 【笔记】Python爬虫之Xpath、BS4解析
    1、Bs4解析#安装bs4importrequestsfrombs4importBeautifulSoup#1url=""resp=requests.get(url)#2.将请求到的数据变成BeautifulSoup对象sp=BeautifulSoup(resp.text,'lxml')#↑加.text↑固定lxml#————————————————......
  • 最简单的python爬虫案例,适合入门学习
    用python从网页爬取数据,网上相关文章很多,但能让零基础初学者轻松上手的却很少。可能是有的作者觉得有些知识点太简单不值得花费精力讲,结果是难者不会会者不难,初学者常常因此而蒙圈。本人也是小白,刚摸索着爬了两个简单的网页数据,经历了初学者易犯的各种糊涂,特总结分享一下,希......
  • Python爬虫案例:简单获取股票、指数、三大报表数据
    Python爬虫案例:简单获取股票、指数、三大报表数据文章目录Python爬虫案例:简单获取股票、指数、三大报表数据介绍1.准备工作2.以不同股票、指数为行,爬取不同日期的数据调用tushare库获取数据,并保存到本地baostock库获取单支股票的详细信息3.爬取三大报表数据使用ak......