2017-10-09 81 views
-1

我是Python新手(实际上第二次尝试学习语言,所以我知道一些东西),并且我正在尝试构建一个脚本来擦除天气预报。python web scraping Weatherforecast

现在我有一个小问题找到正确的html类导入到python。我现在有这样的代码:

import requests 
from bs4 import BeautifulSoup 

page = requests.get("https://openweathermap.org/city/2743477") 
soup = BeautifulSoup(page.content, 'html.parser') 
city_name = soup.find(class_="weather-widget__city-name") 
print(city_name) 

问题是,这只是返回“无”

我发现,通过镀铬的代码搜索和检查网页的类。如果我通过蟒蛇用下面的代码导出HTML页面:

import requests 
from bs4 import BeautifulSoup 

page = requests.get("https://openweathermap.org/city/2743477") 
soup = BeautifulSoup(page.content, 'html.parser') 
city_name = soup.find(class_="weather-widget__city-name") 
print(soup.prettify()) 

然后我看到在cmd中的HTML页面(如预期),但我也无法找到“类_ =‘天气widget__city名’ '所以我并不惊讶,蟒蛇也无法。我的问题是,为什么python给我的html代码不同于Chrome代码显示在网站上的html代码?我是否在尝试通过BeautifulSoup以这种方式查找天气小部件时遇到了问题?

这是一张来自页面的图片,我试图刮去的部分是用红色圈起来的。

Screenshot from website

提前感谢!

+0

你已经得到了你的问题,三个答案,但你还是没有照顾到他们的回答回应,甚至也不觉得有必要说感谢。多么文明! – SIM

回答

0

该网站加载了JS。

Python请求不会激活这些脚本。其中一个脚本负责加载你正在查找的数据(你可以看到它是JS,也许有点jQuery,我没有真正检查,在加载时由旋转圆圈检查)。

我的建议是使用网站API

我没有订阅该网站,所以我不能在这里展示一个例子,但诀窍很简单。您使用基本(免费)计划订阅网站API,获取API密钥并开始向API URL发送获取请求。 这也将进一步简化您的工作,因为您不需要BeautifulSoup进行解析。所有回复均以JSON格式显示。

还有另一种更糟糕的方式,那就是使用selenium。该模块将模拟Web浏览器及其所有的JS激活,HTML渲染,CSS加载机制。

我有两种经验,我强烈建议坚持API(如果该选项存在)。

+0

谢谢你的回答!我已经看过API,但没有得到这个工作(我已经注册了,但每小时只有几个请求被允许,所以我无法测试到我的喜好)。另一方面,我尝试了另一个来自国际空间站的API,它的功能就像一个魅力。所以对于未来我肯定会更关注API。 – Blub21

0

对于使用JS发送更多请求的站点,在我们请求初始URL之后,一种可行的方法是研究Chrome开发人员工具(或任何其他浏览器中的等效项)的网络选项卡。

您通常会发现浏览器请求的大量URL。他们中的大多数对我们的目的来说是不必要其中很少涉及其他网站,如Google,Facebook。

在这种特殊情况下,在请求初始URL之后,您会发现一些'.js'文件正在被检索,之后会有三个脚本(预测,天气,每日)对应于最终得到的数据由浏览器呈现。

从这三者中,您要求的数据来自'天气'脚本。如果您在网络选项卡中点击它,另一侧栏会打开其中将包含头信息,预览等

在头选项卡,你会发现,你需要使用的URL,这是:

https://openweathermap.org/data/2.5/weather?id=2743477&units=metric&appid=b1b15e88fa797225412429c1c50c122a1 

b1b15e88fa797225412429c1c50c122a1可能是分配给浏览器请求的通用API密钥。我不确定。但是我们需要知道的是它不会改变。我试过两种不同的系统,这个值不会改变。

2743477当然是城市ID。您可以下载其网站本身各个城市的参考及其ID:

http://bulk.openweathermap.org/sample/

正如nutmeg64说,该网站实际上是一个JSON文件响应。 API和在浏览器的网络选项卡中找到的此URL的请求都是这种情况。

至于出现在JSON的代码,该网站给你一个参考代码及其含义:

https://openweathermap.org/weather-conditions

有了这些信息,你可以使用requestsjson检索和操纵数据。下面是一个示例脚本:

from pprint import pprint 
import json 

import requests 

city_id = 2743477 
url = 'https://openweathermap.org/data/2.5/weather?id={}&units=metric&appid=b1b15e88fa797225412429c1c50c122a1'.format(city_id) 

req_headers = { 
    'Accept': '*/*', 
    'Accept-Encoding': 'gzip, deflate, br', 
    'Accept-Language': 'en-US,en;q=0.8', 
    'Connection': 'keep-alive', 
    'Host': 'openweathermap.org', 
    'Referer': 'https://openweathermap.org/city/2743477', 
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36' 
} 

s = requests.Session() 
r = s.get(url, headers=req_headers) 

d = json.loads(r.text) 
pprint(d) 

然而,正如nutmeg64说,这是更好地使用API​​,并抵制诱惑,轰炸更多的要求比你真正需要的网站。

你可以找到所有关于他们的API在这里:在BeautifulSoup组合

https://openweathermap.org/current

+0

谢谢你的回答!我试过了代码,它确实帮助我了解了这个网站是如何构建的,并且我确信我可以使用这种技术作为未来的参考 – Blub21

0

使用硒从没有困苦页面得到任何表。这里是你如何能做到:

from selenium import webdriver 
from bs4 import BeautifulSoup 

driver=webdriver.Chrome() 
driver.get("https://openweathermap.org/city/2743477") 
soup = BeautifulSoup(driver.page_source, 'lxml') 
driver.quit() 
table_tag = soup.select(".weather-widget__items")[0] 
tab_data = [[item.text.strip() for item in row_data.select("td")] 
       for row_data in table_tag.select("tr")] 

for data in tab_data: 
    print(data) 

部分结果:

['Wind', 'Gentle Breeze,\n  3.6 m/s, Southwest (220)'] 
['Cloudiness', 'Broken clouds'] 
['Pressure', '1014 hpa'] 
['Humidity', '100 %'] 
['Sunrise', '11:53'] 
+0

感谢您的建议!我一定会考虑它! – Blub21