【问题标题】:Python script to get temperature from google search从谷歌搜索获取温度的 Python 脚本
【发布时间】:2016-05-07 15:23:53
【问题描述】:

我正在制作一个 python 脚本,它将通过搜索关键字温度从谷歌获取温度。 我发现温度值存储在此检查元素代码中的 span id="wob_tm" 中->

<div>
<div class="vk_bk sol-tmp" style="float:left;margin-top:-3px;font-size:64px"><span id="wob_tm" class="wob_t" style="display:inline">
  18
</span><span id="wob_ttm" class="wob_t" style="display:none"> … </span>
</div>

可以看出温度 18 在 span id="wob_tm" 内。 所以,我的python脚本是->

    from bs4 import BeautifulSoup
import requests,sys,webbrowser    

str="temperature"
res = requests.get('http://google.com/search?q=%s'%str)
res.raise_for_status()
examplesoup= BeautifulSoup(res.text,"lxml")    
linkelems=examplesoup.findAll("span",{"id":"wob_tm"})
print linkelems.string.strip()

它给了我这个错误- AttributeError:“NoneType”对象没有属性“字符串” 如何纠正它?这意味着链接元素没有元素。

【问题讨论】:

  • 为什么要打印链接元的长度?
  • 只是为了确保列表链接元素具有要从中提取文本的内容。但奇怪的是,它没有元素。
  • 为什么不使用简单的免费天气 API 而不是抓取 google 页面?
  • 因为自己制作东西感觉很好。
  • 在天气页面我得到它有这个跨度 id =wob_tm。

标签: python beautifulsoup python-requests lxml


【解决方案1】:

从一些实验来看,Google 发送的结果似乎略有不同,具体取决于它认为您使用的浏览器。例如,当我使用 Firefox 时,我会看到 id 为“wob_tm”的跨度,但在运行代码时默认情况下不会。 (我确实得到了一个具有温度的 wob_t 类的跨度,但我也得到了 10 个其他 wob_t 跨度)。尝试将用户代理设置为流行的浏览器,如下所示:

str="temperature"

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1'
}

res = requests.get('http://www.google.com/search?q=%s' % str, headers=headers)
res.raise_for_status()
examplesoup=BeautifulSoup(res.text,'lxml')
linkelems=examplesoup.findAll('span', {'id': 'wob_tm'}) # This now has an element in it

【讨论】:

    【解决方案2】:

    我运行了这段代码(使用 Python 3 和 bs4)并得到了 span 标签的字符串。

    from bs4 import BeautifulSoup
    html_snippet = """<div>
    <div class="vk_bk sol-tmp" style="float:left;margin-top:-3px;font-size:64px"><span id="wob_tm" class="wob_t" style="display:inline">18</span><span id="wob_ttm" class="wob_t" style="display:none"> ... </span></div>"""
    
    soup = BeautifulSoup(html_snippet)
    temp = soup.find("span", id='wob_tm')
    
    print(temp.string)
    

    【讨论】:

      【解决方案3】:

      您正在打印的0 是跨度标记内容的长度,而不是内容本身。 string 属性将为您获取 div 标签的内容:

      from bs4 import BeautifulSoup
      s = """<div>
      <div class="vk_bk sol-tmp" style="float:left;margin-top:-3px;font-size:64px">
      <span id="wob_tm" class="wob_t" style="display:inline">
      18
      </span><span id="wob_ttm" class="wob_t" style="display:none"> … </span>
      </div>"""
      soup = BeautifulSoup(s)
      temperature = soup.find("span", id="wob_tm")
      print(temperature.string.strip())
      # 18
      

      【讨论】:

      • 即使我如上所示更改了我的代码,它仍然给我错误,即 NoneType 对象没有名为字符串的属性。
      • 我认为您的 html 缺少起始 div 标记的结尾 ">",这就是无法识别 span 标记(ID 为“wob_tm”)的原因
      【解决方案4】:

      确保您使用的是user-agent,这样Google 就不会将您的请求视为python-requests,这是默认的requestsUser-Agent。如果只需要提取温度数据,可以使用.select_one()bs4方法。

      >>> soup.select_one('#wob_tm').text
      '85°F'
      

      提取更多in the online IDE的代码和示例:

      from bs4 import BeautifulSoup
      import requests, lxml
      
      headers = {
        "User-Agent":
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.19582"
      }
      
      params = {
        "q": "london weather",
        "hl": "en",
      }
      
      response = requests.get('https://www.google.com/search', headers=headers, params=params).text
      soup = BeautifulSoup(response, 'lxml')
      
      tempature = soup.select_one('#wob_tm').text
      print(f'Tempature: {tempature}')
      
      ---
      # Tempature: 73°F
      

      或者,您可以使用来自 SerpApi 的 Google Direct Answer Box API。这是一个带有免费计划的付费 API。

      要集成的代码:

      from serpapi import GoogleSearch
      import os
      
      params = {
        "engine": "google",
        "q": "london weather",
        "api_key": os.getenv("API_KEY"),
        "hl": "en",
      }
      
      search = GoogleSearch(params)
      results = search.get_dict()
      
      loc = results['answer_box']['location']
      weather_date = results['answer_box']['date']
      weather = results['answer_box']['weather']
      temp = results['answer_box']['temperature']
      unit = results['answer_box']['unit']
      precipitation = results['answer_box']['precipitation']
      humidity = results['answer_box']['humidity']
      wind = results['answer_box']['wind']
      
      forecast = results['answer_box']['forecast']
      
      print(f'{loc}\n{weather_date}\n{weather}\n{temp}\n{unit}\n{precipitation}\n{humidity}\n{wind}\n{forecast}')
      
      ---------
      '''
      London, UK
      Wednesday 1:00 PM
      Partly cloudy
      73°F
      0%
      55%
      7 mph
      
      [{'day': 'Wednesday', 'weather': 'Partly cloudy', 'temperature': {'high': '74', 'low': '59'}, 'thumbnail': 'https://ssl.gstatic.com/onebox/weather/48/partly_cloudy.png'}..]
      '''
      

      免责声明,我为 SerpApi 工作。

      【讨论】:

        猜你喜欢
        • 2012-08-19
        • 2017-07-02
        • 1970-01-01
        • 1970-01-01
        • 2016-10-11
        • 1970-01-01
        • 2023-02-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多