qdfxy 发表于 2020-10-19 10:30

scrapy框架爬虫

本帖最后由 qdfxy 于 2020-10-19 10:55 编辑

记录新手的第一次爬虫
目标网址:中国天气网:http://www.weather.com.cn/
小白在南通,就爬南通的天气:http://www.weather.com.cn/weather/101190501.shtml


[*]scrapy startproject weather
[*]cd weather
[*]scrapy genspider NTtianqi www.weather.com.cn/weather/101190501.shtml
[*]来看一下创建好的目录
[*]
[*]编写items.py:这次我们来先编写items,十分的简单,只需要将希望获取的字段名填写进去:
[*]import scrapy
   
class WeatherItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    date = scrapy.Field()
    temperature = scrapy.Field()
    weather = scrapy.Field()
    wind = scrapy.Field()
[*]编写Spider:这个部分使我们整个爬虫的核心!!主要目的是:将Downloader发给我们的Response里筛选数据,并返回给PIPELINE处理
[*]import scrapy

from weather.items import WeatherItem
class NttianqiSpider(scrapy.Spider):
    name = 'NTtianqi'
    allowed_domains = ['www.weather.com.cn/weather/101190501.shtml']
    start_urls = ['http://www.weather.com.cn/weather/101190501.shtml']

    def parse(self, response):
      '''
      筛选信息的函数:
      date = 日期
      temperature = 当天的温度
      weather = 当天的天气
      wind = 当天的风向
      '''

      # 先建立一个列表,用来保存每天的信息
      items = []

      # 找到包裹着天气信息的div
      day = response.xpath('//ul[@class="t clearfix"]')

      # 循环筛选出每天的信息:
      for i in list(range(7)):
            # 先申请一个weatheritem 的类型来保存结果
            item = WeatherItem()

            # 观察网页,并找到需要的数据
            item['date'] = day.xpath('./li[' + str(i + 1) + ']/h1//text()').extract()

            item['temperature'] = day.xpath('./li[' + str(i + 1) + ']/p[@class="tem"]/i/text()').extract()

            item['weather'] = day.xpath('./li[' + str(i + 1) + ']/p[@class="wea"]/text()').extract()

            item['wind'] = day.xpath('./li[' + str(i + 1) + ']/p[@class="win"]/em/span/@title').extract() + \
                           day.xpath('./li[' + str(i + 1) + ']/p[@class="win"]/i/text()').extract()

            items.append(item)

      return items
[*]编写PIPELINE:我们知道,pipelines.py是用来处理收尾爬虫抓到的数据的,
一般情况下,我们会将数据存到本地
[*]

[*]文本形式: 最基本的存储方式
[*]json格式 :方便调用
[*]数据库: 数据量比较大时选择的存储方式
[*]TXT(文本)格式:
[*]import os import requestsimport jsonimport codecsimport pymysql
[*]class WeatherPipeline(object):
    def process_item(self, item, spider):
   
      print(item)
      # print(item)
      # 获取当前工作目录
      base_dir = os.getcwd()
      # 文件存在data目录下的weather.txt文件内,data目录和txt文件需要自己事先建立好
      filename = base_dir + '/data/weather.txt'
   
      # 从内存以追加的方式打开文件,并写入对应的数据
      with open(filename, 'a') as f:
            f.write(item['date'] + '\n')
            f.write(item['temperature'] + '\n')
            f.write(item['weather'] + '\n')
            f.write(item['wind'] + '\n\n')
   
      return item
[*]json格式数据:我们想要输出json格式的数据,最方便的是在PIPELINE里自定义一个class
[*]class W2json(object):
    def process_item(self, item, spider):
      '''
      讲爬取的信息保存到json
      方便其他程序员调用
      '''
      base_dir = os.getcwd()
      filename = base_dir + '/data/weather.json'
   
      # 打开json文件,向里面以dumps的方式吸入数据
      # 注意需要有一个参数ensure_ascii=False ,不然数据会直接为utf编码的方式存入比如:“/xe15”
      with codecs.open(filename, 'a') as f:
            line = json.dumps(dict(item), ensure_ascii=False) + '\n'
            f.write(line)
   
      return item
[*]数据库格式(mysql):
[*]
在本地安装mysql:
linux和mac都有很强大的包管理软件,如apt,brew等等window 可以直接去官网下载安装包。由于我是Mac,所以我是说Mac的安装方式了。
$ brew install mysql在安装的过程中,他会要求你填写root用户的密码,这里的root并不是系统层面上的超级用户,是mysql数据库的超级用户。
安装完成后mysql服务是默认启动的,
如果重启了电脑,需要这样启动(mac):
$ mysql.server start
[*]登录mysql并创建scrapy用的数据库:
[*]# 登录进mysql
$ mysql -uroot -p

# 创建数据库:ScrapyDB ,以utf8位编码格式,每条语句以’;‘结尾
CREATE DATABASE ScrapyDB CHARACTER SET 'utf8';

# 选中刚才创建的表:
use ScrapyDB;

# 创建我们需要的字段:字段要和我们代码里一一对应,方便我们一会写sql语句
CREATE TABLE weather(
id INT AUTO_INCREMENT,
date char(24),
temperature char(24),
weather char(24),
wind char(24),
PRIMARY KEY(id) )ENGINE=InnoDB DEFAULT CHARSET='utf8'
来看一下weather表长啥样:


show columns from weather
或者:desc weather
[*]安装Python的mysql模块:
[*]pip install pymysql
[*]class W2mysql(object):
    def process_item(self, item, spider):
      '''
      将爬取的信息保存到mysql
      '''

      # 将item里的数据拿出来
      date = item['date']
      temperature = item['temperature']
      weather = item['weather']
      wind = item['wind']

      # 和本地的scrapyDB数据库建立连接
      connection = pymysql.connect(
            host='127.0.0.1',# 连接的是本地数据库
            user='root',      # 自己的mysql用户名
            passwd='********',# 自己的密码
            db='ScrapyDB',      # 数据库的名字
            charset='utf8mb4',   # 默认的编码方式:
            cursorclass=pymysql.cursors.DictCursor)

      try:
            with connection.cursor() as cursor:
                # 创建更新值的sql语句
                sql = """INSERT INTO WEATHER(date,temperature,weather,wind)
                        VALUES (%s, %s, %s, %s)"""
                # 执行sql语句
                # excute 的第二个参数可以将sql缺省语句补全,一般以元组的格式
                cursor.execute(
                  sql, (date, temperature, weather, wind))

            # 提交本次插入的记录
            connection.commit()
      finally:
            # 关闭连接
            connection.close()

      return item
[*]编写Settings.py我们需要在Settings.py将我们写好的PIPELINE添加进去,
scrapy才能够跑起来这里只需要增加一个dict格式的ITEM_PIPELINES,
数字value可以自定义,数字越小的优先处理
[*]BOT_NAME = 'weather'

SPIDER_MODULES = ['weather.spiders']
NEWSPIDER_MODULE = 'weather.spiders'

ROBOTSTXT_OBEY = True

ITEM_PIPELINES = {
   'weather.pipelines.WeatherPipeline': 300,
   'weather.pipelines.W2json': 400,
   'weather.pipelines.W2mysql': 300,
}
[*]在weather里创建main.py用来跑项目
[*]from scrapy import cmdline
cmdline.execute("scrapy crawl HFtianqi ".split())
[*]这样就可以了







枫子树 发表于 2020-10-19 10:36

qdfxy 发表于 2020-10-19 10:58

枫子树 发表于 2020-10-19 10:36
发错板块了吧这是求助区

我是发错了吗 我记得是讨论区啊

838384855 发表于 2020-10-19 11:42

感谢分享,存到库里到时候自己弄个接口将数据转发出去岂不就有了自己的天气数据源 现在做的小程序和项目基本用的都现成的天气接口 不是很精准而且还有次数限制很不方便 这么一来就简单了 感谢!

andyfky 发表于 2020-10-19 13:34

真正学习了。
页: [1]
查看完整版本: scrapy框架爬虫