注意防范高温!通过splash爬取高温预警信息

需求分析

最近的天气实在是太热了,据天气预报显示,很多地方这周温度将会超过40度。这样的高温天气之下,靠喝冰饮,吃雪糕都不管用了,总之,只要离开了空调房,就感觉自己要融化掉了

怎么办呢?我们必须要做好防范!今天我准备通过爬虫,爬取一下高温预警信息。话说,关于天气预警信息,我在上个月的时候已经做过一次了,通过python爬取天气预警信息。但是呢,那次是全部的天气预警信息,不是专门针对高温的,所以说像台风,暴雨,雷电等等也会包括在内,这不是我们现在需要的。因此,本期的任务,就是对之前的天气预警信息进行一些改造,使其变成专门的高温预警信息

当然啦,我们也不会只是简单的对其进行小幅度的修改,这次我决定将其全面重做。主要的区别在于,上次我们使用的是selenium,并且在这期间进行了一次iframe标签的切换。而这一次呢,我准备改为使用splash,这个在技术上就完全不一样了。如果你有兴趣的话,也可以根据这次的结果对比一下selenium的实现和splash的实现有什么样的区别

实现分析

首先呢,我们观察一下页面,我们需要的页面大概就像这样

注意防范高温!通过splash爬取高温预警信息_第1张图片

那么,如何通过splash获取呢?首先呢,毫无疑问,我们需要先搭建一个splash服务,我使用的是默认的本机搭建的splash,采用了默认的8050端口,这个可以根据你自己的需要进行修改

然后呢,我们可以通过splash的快速接口,也就是render.html简单的尝试一下

import requests
from base64 import b64decode

b_url = b64decode("aHR0cDovL3d3dy53ZWF0aGVyLmNvbS5jbi9hbGFybS9uZXdhbGFybV8yMDIwLnNodG1s").decode()
url = "http://localhost:8050/render.html?url=" + b_url

r = requests.get(url)
print(r.text)

哦,糟了,不出意外的话是出意外了。这个返回的结果中怎么没有数据呢?这是怎么回事呢?太奇怪了吧?

众所周知,如果直接通过requests发起请求的话,是得不到数据的,原因在于requests没有执行js的渲染,所以说得不到动态页面,那么现在为什么我们换了splash以后还是没数据呢?怎么看起来这个结果和requests直接得到的结果差不多呢?这到底是怎么回事呢?

难道说,splash没有执行js的动态渲染吗?为什么呢?难道说,这个地址有什么“黑科技”,阻挡了splash执行js吗?难道这里只可以使用selenium吗?

当然不,其实呢,这个原因很简单。就是我们的请求太快了,没有让它等待,第一时间就把结果返回了。所以说splash还没有来得及执行完js,我们就已经要求其返回结果了,所以说我们没有得到渲染完成后的页面

解决的办法呢,就更简单的,我们只需要让其等一会,就可以了。当然,在这里使用的可不是time.sleep(),我们需要做的是给它加上一个wait参数

import requests
from base64 import b64decode

b_url = b64decode("aHR0cDovL3d3dy53ZWF0aGVyLmNvbS5jbi9hbGFybS9uZXdhbGFybV8yMDIwLnNodG1s").decode()
url = "http://localhost:8050/render.html?wait=3&url=" + b_url

r = requests.get(url)
print(r.text)

看吧,这就是一个非常容易就可以解决了的小问题,总共也才只加了6个字符。但是如果你对splash不熟悉,或者是一个初学者的话,很可能就因为这一点点小问题就彻底卡住了,再也找不到解决办法了。可能这就是学习程序的困难吧

完整代码展示

import requests
from urllib.parse import quote
from base64 import b64decode
from lxml import etree

b_url = b64decode("aHR0cDovL3d3dy53ZWF0aGVyLmNvbS5jbi9hbGFybS9uZXdhbGFybV8yMDIwLnNodG1s").decode()

lua = """
function main(splash)
    splash:go("%s")
    splash:wait(1)
    splash:evaljs("document.getElementById('kind').value = '07';")
    splash:wait(0.5)
    splash:evaljs("document.getElementById('Submit').click();")
    splash:wait(1)
    return splash:html()
end
""" % b_url


url = "http://localhost:8050/execute?lua_source=" + quote(lua)
r = requests.get(url)

html = etree.HTML(r.text)
lis = html.xpath("//ul[@class='dDUl']/li")

for i in lis:
    print(i.xpath("./span[2]/text()")[0], ":", i.xpath("./a[2]/text()")[0])

以下是程序的运行结果,可以看到,我们的程序已经非常好的完成了任务。得到了高温的预警信息,我们就可以提前做好防范啦。饮料,棒冰,通通准备起来!

注意防范高温!通过splash爬取高温预警信息_第2张图片


我知道有很多的初学者,对我的文章内容可能并不关心,直接就划到最后,复制完整代码拿去运行了,所以说,可能会错过一些细节

因此,我需要额外提醒一下,本次的程序使用了splash,你需要在本机搭建一个splash服务,才能够运行这个程序,如果你不管这个,直接运行是运行不了的,这并不是程序的问题。当然,如果你在其他的机器上有splash的服务的话,也可以根据需要进行修改

你可能感兴趣的:(爬虫程序,爬虫,python)