zoukankan      html  css  js  c++  java
  • scrapy爬虫事件以及数据保存为txt,json,mysql

    今天要爬取的网页是虎嗅网

    我们将完成如下几个步骤:

    • 创建一个新的Scrapy工程
    • 定义你所需要要抽取的Item对象
    • 编写一个spider来爬取某个网站并提取出所有的Item对象
    • 编写一个Item Pipline来存储提取出来的Item对象

    创建Scrapy工程

    在任何目录下执行如下命令

    scrapy startproject coolscrapy
    cd coolscrapy 
    scrapy genspider huxiu huxiu.com

    我们看看创建的工程目录结构:(news.json,news.txt是最后结果保存的)

    定义Item

    我们通过创建一个scrapy.Item类,并定义它的类型为scrapy.Field的属性, 我们准备将虎嗅网新闻列表的名称、链接地址和摘要爬取下来。

     1 import scrapy
     2 
     3 
     4 class CoolscrapyItem(scrapy.Item):
     5     # define the fields for your item here like:
     6     # name = scrapy.Field()
     7     title = scrapy.Field() #标题
     8     link = scrapy.Field() #链接
     9     desc = scrapy.Field() #简述
    10     posttime = scrapy.Field() #发布时间

    编写Spider

    蜘蛛就是你定义的一些类,Scrapy使用它们来从一个domain(或domain组)爬取信息。 在蜘蛛类中定义了一个初始化的URL下载列表,以及怎样跟踪链接,如何解析页面内容来提取Item。

    定义一个Spider,只需继承scrapy.Spider类并定于一些属性:

    • name: Spider名称,必须是唯一的
    • start_urls: 初始化下载链接URL
    • parse(): 用来解析下载后的Response对象,该对象也是这个方法的唯一参数。 它负责解析返回页面数据并提取出相应的Item(返回Item对象),还有其他合法的链接URL(返回Request对象)。

    我们打开在coolscrapy/spiders文件夹下面的huxiu.py,内容如下:

     1 # -*- coding: utf-8 -*-
     2 import scrapy
     3 from coolscrapy.items import CoolscrapyItem
     4 
     5 class HuxiuSpider(scrapy.Spider):
     6     name = "huxiu"
     7     allowed_domains = ["huxiu.com"]
     8     start_urls = ['http://huxiu.com/index.php']
     9 
    10     def parse(self, response):
    11         items = []
    12         data = response.xpath('//div[@class="mod-info-flow"]/div/div[@class="mob-ctt"]')
    13         for sel in data:
    14             item = CoolscrapyItem()
    15             if len(sel.xpath('./h2/a/text()').extract()) <= 0:
    16                 item['title'] = 'No title'
    17             else:
    18                 item['title'] = sel.xpath('./h2/a/text()').extract()[0]
    19             if len(sel.xpath('./h2/a/@href').extract()) <= 0:
    20                 item['link'] = 'link在哪里!!!!!!!!'
    21             else:
    22                 item['link'] = sel.xpath('./h2/a/@href').extract()[0]
    23             url = response.urljoin(item['link'])
    24             if len(sel.xpath('div[@class="mob-sub"]/text()').extract()) <= 0:
    25                 item['desc'] = '啥也没有哦...'
    26             else:
    27                 item['desc'] = sel.xpath('div[@class="mob-sub"]/text()').extract()[0]
    28             #item['posttime'] = sel.xpath('./div[@class="mob-author"]/span/@text()').extract()[0]
    29             print(item['title'], item['link'], item['desc'])
    30             items.append(item)
    31         return items

    现在可以在终端运行了,是可以打印每个新闻信息的。

    scrapy crawl huxiu

    如果一切正常,应该可以打印出每一个新闻

    处理链接

    如果想继续跟踪每个新闻链接进去,看看它的详细内容的话,那么可以在parse()方法中返回一个Request对象, 然后注册一个回调函数来解析新闻详情。

    下面继续编写huxiu.py

    # -*- coding: utf-8 -*-
    import scrapy
    from coolscrapy.items import CoolscrapyItem
    
    class HuxiuSpider(scrapy.Spider):
        name = "huxiu"
        allowed_domains = ["huxiu.com"]
        start_urls = ['http://huxiu.com/index.php']
    
        def parse(self, response):
            #items = []
            data = response.xpath('//div[@class="mod-info-flow"]/div/div[@class="mob-ctt"]')
            for sel in data:
                item = CoolscrapyItem()
                if len(sel.xpath('./h2/a/text()').extract()) <= 0:
                    item['title'] = 'No title'
                else:
                    item['title'] = sel.xpath('./h2/a/text()').extract()[0]
                if len(sel.xpath('./h2/a/@href').extract()) <= 0:
                    item['link'] = 'link在哪里!!!!!!!!'
                else:
                    item['link'] = sel.xpath('./h2/a/@href').extract()[0]
                url = response.urljoin(item['link'])
                if len(sel.xpath('div[@class="mob-sub"]/text()').extract()) <= 0:
                    item['desc'] = '啥也没有哦...'
                else:
                    item['desc'] = sel.xpath('div[@class="mob-sub"]/text()').extract()[0]
                #item['posttime'] = sel.xpath('./div[@class="mob-author"]/span/@text()').extract()[0]
                print(item['title'], item['link'], item['desc'])
                #items.append(item)
            #return items
                yield scrapy.Request(url,callback=self.parse_article)
    
        def parse_article(self,response):
            detail = response.xpath('//div[@class="article-wrap"]')
            item = CoolscrapyItem()
            item['title'] = detail.xpath('./h1/text()')[0].extract().strip()
            item['link'] = response.url
            item['posttime'] = detail.xpath('./div/div[@class="column-link-box"]/span[1]/text()')[0].extract()
            print(item['title'],item['link'],item['posttime'])
            yield item

     现在parse只提取感兴趣的链接,然后将链接内容解析交给另外的方法去处理了。 你可以基于这个构建更加复杂的爬虫程序了。

    导出抓取数据

    最简单的保存抓取数据的方式是使用json格式的文件保存在本地,像下面这样运行:

    scrapey crawl huxiu -o items.json

    一般构建爬虫系统,建议自己编写Item Pipeline

    数据保存为TXT/JSON/MySql

    1.数据保存为TXT

    打开Pipeline.py

     1 import codecs
     2 import os
     3 import json
     4 import pymysql
     5 
     6 class CoolscrapyPipeline(object):#需要在setting.py里设置'coolscrapy.piplines.CoolscrapyPipeline':300
     7     def process_item(self, item, spider):
     8         # 获取当前工作目录
     9         base_dir = os.getcwd()
    10         fiename = base_dir + '/news.txt'
    11         # 从内存以追加的方式打开文件,并写入对应的数据
    12         with open(fiename, 'a') as f:
    13             f.write(item['title'] + '
    ')
    14             f.write(item['link'] + '
    ')
    15             f.write(item['posttime'] + '
    
    ')
    16         return item

    2.保存为json格式

    在Pipeline.py里面新建一个类

     1 #以下两种写法保存json格式,需要在settings里面设置'coolscrapy.pipelines.JsonPipeline': 200
     2 
     3 class JsonPipeline(object):
     4     def __init__(self):
     5         self.file = codecs.open('logs.json', 'w', encoding='utf-8')
     6     def process_item(self, item, spider):
     7         line = json.dumps(dict(item), ensure_ascii=False) + "
    "
     8         self.file.write(line)
     9         return item
    10     def spider_closed(self, spider):
    11         self.file.close()
    12 
    13 
    14 class JsonPipeline(object):
    15     def process_item(self, item, spider):
    16         base_dir = os.getcwd()
    17         filename = base_dir + '/news.json'
    18         # 打开json文件,向里面以dumps的方式吸入数据
    19         # 注意需要有一个参数ensure_ascii=False ,不然数据会直接为utf编码的方式存入比如
    20         # :“/xe15”
    21         with codecs.open(filename, 'a') as f:
    22             line = json.dumps(dict(item), ensure_ascii=False) + '
    '
    23             f.write(line)
    24         return item

    上面是两种写法,都是一样的

    3.保存到mysql

    保存到数据库需要建立表格newsDB,详情请参考http://www.cnblogs.com/freeman818/p/7223161.html

     在Pipeline.py里面新建一个类

     1 class mysqlPipeline(object):
     2     def process_item(self,item,spider):
     3         '''
     4         将爬取的信息保存到mysql
     5         '''
     6         # 将item里的数据拿出来
     7         title = item['title']
     8         link = item['link']
     9         posttime = item['posttime']
    10 
    11         # 和本地的newsDB数据库建立连接
    12         db = pymysql.connect(
    13             host='localhost',  # 连接的是本地数据库
    14             user='root',  # 自己的mysql用户名
    15             passwd='123456',  # 自己的密码
    16             db='newsDB',  # 数据库的名字
    17             charset='utf8mb4',  # 默认的编码方式:
    18             cursorclass=pymysql.cursors.DictCursor)
    19         try:
    20             # 使用cursor()方法获取操作游标
    21             cursor = db.cursor()
    22             # SQL 插入语句
    23             sql = "INSERT INTO NEWS(title,link,posttime) 
    24                   VALUES ('%s', '%s', '%s')" % (title,link,posttime)
    25             # 执行SQL语句
    26             cursor.execute(sql)
    27             # 提交修改
    28             db.commit()
    29         finally:
    30             # 关闭连接
    31             db.close()
    32         return item

    编写Settings.py

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

    1 ITEM_PIPELINES={'coolscrapy.pipelines.CoolscrapyPipeline':300,
    2                 'coolscrapy.pipelines.JsonPipeline': 200,
    3                 'coolscrapy.pipelines.mysqlPipeline': 100,
    4 }

    下面让程序跑起来

    scrape crawl huxiu

    看看结果:

     

    好了,这次就到这里。代码要自己敲才会慢慢熟练。

  • 相关阅读:
    盒子模型2+浮动
    盒子模型
    CSS背景和精灵图
    线程间的通信的实现
    操作系统中线程与进程
    java中的互斥锁和信号量的区别
    Java中的常见异常
    JVM面试问题
    软件测试分类
    软件测试
  • 原文地址:https://www.cnblogs.com/freeman818/p/7228976.html
Copyright © 2011-2022 走看看