运维开发网

实操 | 从0到1教你用Python来爬取整站天气网

运维开发网 https://www.qedev.com 2020-11-25 08:44 出处:51CTO 作者:涛哥聊python
ScrapyScrapy是Python开发的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。一、安装scrapy安装TwistedTwisted:为 Python 提供的基于事件驱动的网络引擎包。在下面网址安装Twistedurl:https://www.lfd.uci.edu/~gohlke/pythonlibs/安装scrapycmd输入pip ins

Scrapy

Scrapy是Python开发的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。

一、安装scrapy

安装Twisted
  • Twisted:为 Python 提供的基于事件驱动的网络引擎包。

  • 在下面网址安装Twisted

url:https://www.lfd.uci.edu/~gohlke/pythonlibs/

实操 | 从0到1教你用Python来爬取整站天气网

安装scrapy
  • cmd输入pip install scrapy

  • 安装完毕,cmd里输入scrapy出现安装成功。

实操 | 从0到1教你用Python来爬取整站天气网

二、了解scrapy

实操 | 从0到1教你用Python来爬取整站天气网

Scrapy的组件

  • 引擎,用来处理整个系统的数据流处理,触发事务。

  • 调度器,用来接受引擎发过来的请求,压入队列中,并在引擎再次请求的时候返回。

  • 下载器,用于下载网页内容,并将网页内容返回给蜘蛛。

  • 蜘蛛,蜘蛛是主要干活的,用它来制订特定域名或网页的解析规则。

  • 项目管道,负责处理有蜘蛛从网页中抽取的项目,主要任务是清晰、验证和存储数据。当页面被蜘蛛解析后,将被发送到项目管道,并经过几个特定的次序处理数据。

  • 下载器中间件,位于Scrapy引擎和下载器之间的钩子框架,主要是处理Scrapy引擎与下载器之间的请求及响应。

  • 蜘蛛中间件,介于Scrapy引擎和蜘蛛之间的钩子框架,主要工作是处理蜘蛛的响应输入和请求输出。

  • 调度中间件,介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。

其处理流程为:

  • 引擎打开一个域名时,蜘蛛处理这个域名,并让蜘蛛获取第一个爬取的URL。

  • 引擎从蜘蛛那获取第一个需要爬取的URL,然后作为请求在调度中进行调度。

  • 引擎从调度那获取接下来进行爬取的页面。

  • 调度将下一个爬取的URL返回给引擎,引擎将他们通过下载中间件发送到下载器。

  • 当网页被下载器下载完成以后,响应内容通过下载中间件被发送到引擎。

  • 引擎收到下载器的响应并将它通过蜘蛛中间件发送到蜘蛛进行处理。

  • 蜘蛛处理响应并返回爬取到的项目,然后给引擎发送新的请求。

  • 引擎将抓取到的项目项目管道,并向调度发送请求。

  • 系统重复第二部后面的操作,直到调度中没有请求。

三、项目分析

爬取天气网城市的信息url : https://www.aqistudy.cn/historydata/

实操 | 从0到1教你用Python来爬取整站天气网

爬取主要的信息: 热门城市每一天的空气质量信息

实操 | 从0到1教你用Python来爬取整站天气网

点击月份还有爬取每天的空气质量信息

四、新建项目

  • 新建文件夹命令为天气网爬虫

  • cd到根目录,打开cmd,运行scrapy startproject weather_spider

实操 | 从0到1教你用Python来爬取整站天气网

  • 创建spider

cd到根目录,运行scrapy genspider weather www.aqistudy.cn/historydata

实操 | 从0到1教你用Python来爬取整站天气网

这里的weather是spider的名字
  • 创建的路径如下:

实操 | 从0到1教你用Python来爬取整站天气网

五、代码编写

对于scrapy,第一步,必须编写item.py,明确爬取的对象

  • item.py

 scrapy

    
    
    
    city = scrapy.Field()
    date = scrapy.Field()
    aqi = scrapy.Field()
    level = scrapy.Field()
    pm25 = scrapy.Field()
    pm10 = scrapy.Field()
    so2 = scrapy.Field()
    co = scrapy.Field()
    no2 = scrapy.Field()
    o3_8h = scrapy.Field()

对于爬取必须伪装好UA,在setting.py中定义MY_USER_AGENT来存放UA,注意在settings中命名必须大写

  • settings.py

MY_USER_AGENT = [
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
    ,
]

在定义好UA后,在middlewares.py中创建RandomUserAgentMiddleware

  • middlewares.py

 random

    
        self.user_agents = user_agents

    @classmethod
    
        
        s = cls(user_agents=crawler.settings.get())
         s

    
        agent = random.choice(self.user_agents)
        request.headers[] = agent

注意要在settings.py中激活,必须是900,来去掉scrapy本身的UA

  • setting.py

DOWNLOADER_MIDDLEWARES = {
   :,
}

开始编写最重要的spider.py,推荐使用scrapy.shell来一步一步调试

  • 先拿到所有的城市

实操 | 从0到1教你用Python来爬取整站天气网

在scrapy中xpath方法和lxml中的xpath语法一样

实操 | 从0到1教你用Python来爬取整站天气网

我们可以看出url中缺少前面的部分,follow方法可以自动拼接url,通过meta方法来传递需要保存的city名字,通过callback方法来调度将下一个爬取的URL

  • weather.py

    city_urls = response.xpath().extract()[:]
    city_names = response.xpath().extract()[:]
    self.logger.info(.format(city_names[]))
     city_url, city_name  zip(city_urls, city_names):
        
         response.follow(url=city_url, meta={: city_name}, callback=self.parse_month)

这时就是定义parse_month函数,首先分析月份的详情页,拿到月份的url

实操 | 从0到1教你用Python来爬取整站天气网

还是在scrapy.shell 中一步一步调试

实操 | 从0到1教你用Python来爬取整站天气网

通过follow方法拼接url,meta来传递city_name要保存的城市名字,selenium:True先不管然后通过callback方法来调度将下一个爬取的URL,即就是天的爬取详细页

  • weather.py

    
    city_name = response.meta[]
    self.logger.info(.format(city_name[]))
    
    month_urls = response.xpath().extract()[:]
     month_url  month_urls:
         response.follow(url=month_url, meta={: city_name, : }, callback=self.parse_day_data)

现在将日的详细页的信息通过xpah来取出

实操 | 从0到1教你用Python来爬取整站天气网

发现竟然为空

实操 | 从0到1教你用Python来爬取整站天气网

同时发现了源代码没有该信息

实操 | 从0到1教你用Python来爬取整站天气网

说明了是通过js生成的数据,scrapy只能爬静态的信息,所以引出的scrapy对接selenium的知识点,所以上面meta传递的参数就是告诉scrapy使用selenium来爬取。复写WeatherSpiderDownloaderMiddleware下载中间件中的process_request函数方法middlewares.py

 time
 scrapy
 selenium  webdriver
 selenium.webdriver.chrome.options  Options

    
         request.meta.get():
            
            chrome_options = Options()
            
            chrome_options.add_argument()
            driver = webdriver.Chrome(chrome_options=chrome_options)
            
            driver.get(request.url)
            time.sleep()  
            html = driver.page_source
            driver.quit()
             scrapy.http.HtmlResponse(url=request.url, body=html, encoding=, request=request)

激活WeatherSpiderDownloaderMiddleware

DOWNLOADER_MIDDLEWARES = {
   : ,
   :,
}

最后编写weather.py中的剩下代码

 ..items  WeatherSpiderItem

    

    node_list = response.xpath()
    
    node_list.pop()
    print(response.body)
    print()
    print(node_list)
     node  node_list:
        item = WeatherSpiderItem
        item[] = response.meta[]
        item[] = node.xpath().extract_first()
        item[] = node.xpath().extract_first()
        item[] = node.xpath().extract_first()
        item[] = node.xpath().extract_first()
        item[] = node.xpath().extract_first()
        item[] = node.xpath().extract_first()
        item[] = node.xpath().extract_first()
        item[] = node.xpath().extract_first()
        item[] = node.xpath().extract_first()
         item

六、运行项目

一定要注意项目的根目录执行命令,可以通过scrapy list查看是否存在项目

实操 | 从0到1教你用Python来爬取整站天气网

scrapy保存信息的最简单的方法主要有四种,-o 输出指定格式的文件,命令如下:默认json

  • scrapy crawl weather -o spider.json

json lines格式,默认为Unicode编码

  • scrapy crawl weather -o spider..jl

csv 逗号表达式,可用Excel打开

  • scrapy crawl weather -o spider..csv

xml格式

  • scrapy crawl weather -o spider..xml

但是保存的编码不对,必须在settings中加入FEED_EXPORT_ENCODING = 'utf-8'

七、入库操作

这里入的库是Mongodb,在settings.py中配置

MONGO_URI= 
MONGO_DB=

对于入门主要处理的是pipelines中

  • pipelines.py

 pymongo


    
        self.mongo_uri=mongo_uri
        self.mongo_db=mongo_db

    @classmethod
    
         cls(
            mongo_uri=crawler.settings.get(),
            mongo_db=crawler.settings.get()
        )

      
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    
        name = item.__class__.__name__
        self.db[name].insert(dict(item))  
         item

      
        self.client.close()
  • 在settings中激活pipelines

ITEM_PIPELINES = {
   : ,
}

效果如下

实操 | 从0到1教你用Python来爬取整站天气网

八、结语

我们本次通过爬取天气网站的来作为学习 Scrapy 的,这里展示的关于 Scrapy 大部分的知识点。如果改写列表,就可以爬取北京所有的天气信息,当然还可以爬取全部城市的天气信息,即这个天气网的全部内容基本都爬取。

扫码领视频副本.gif

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号