ITPub博客

首页 > 应用开发 > > 使用scarpy爬取文章并保存为json文本

使用scarpy爬取文章并保存为json文本

作者:skyweave 时间:2019-08-16 09:32:31 0 删除 编辑

scarpy是python爬虫界最著名的框架,最近使用了下确实很方便,其底层使用的Twisted使用异步非阻塞的方式速度是相当的快(比自己用requests快多了),这里介绍下使用scarpy框架爬取文章和图片,并进行二层爬取文章的内容,然后以dict形式保存为json文件(也可以保存到其他存储介质,如数据库,其他文件存储介质)

    

        环境: python3.7   scarpy1.7.3  都是当前最新版

        安装: pip install scrapy=1.7.3

        创建项目:  scrapy startproject demospider

       

  一. 定义item(爬取的数据结构)

    编辑items.py文件,定义各项数据

import scrapy

class TutorialItem(scrapy.Item):

# define the fields for your item here like:

# name = scrapy.Field()

link = scrapy.Field()

title = scrapy.Field()

text = scrapy.Field()

image_url = scrapy.Field()

author = scrapy.Field()

image_paths = scrapy.Field()

    二. 定义爬取方法

        这是最关键的一步,在这里将会解析获取到的html文本,使用scarpy自带的selector解析获取需要的数据。关于selector语法比较多,官方并没有给过多案例,推荐https://www.jianshu.com/p/489c5d21cdc7, 虽然没有过多例子,但是理论比较全,想要的方法基本都可以找到。

        在spider目录下新建demo_spider.py文件

import scrapy

from demospider.items import TutorialItem

class ImageSpider(scrapy.Spider):

name = 'imagespider'       # 应用名,执行时使用

start_urls = [

'http://www.itpub.net/category/yunwei/'   # 可以写多个,分别进行爬取处理

]

def parse(self, response):                #固定方法,response为每次处理后返回的html,这里主要处理采集第一层页面的数据

for article in response.css('article.xin_hover'):

item = TutorialItem()  #必须要新建,不然获取的数据都会一样                        

item['link'] = article.css('div.post__thumb a::attr("href")').get()

item['image_url'] = article.css('div.post__thumb img::attr("data-src")').extract()

item['title'] = article.css('h3.post__title a::text').get()

item['author'] = article.css('a.entry-author__name::text').get()

#这里处理第二层连接,文章的具体内容页面

yield scrapy.Request(item['link'],meta={'item': item}, callback=self.context_parse)

def context_parse(self,response):

item = response.meta['item']

# 有两种方法采集文章内容,这里推荐xpath(xpath属于贪婪匹配,css精确匹配)

# item['text'] = response.css('div.entry-content p::text').extract()

item['text'] = response.xpath("//div[@class='entry-content typography-copy']//text()").extract()

        yield item

     三. 定义pipeline

    这步对采集到的数据进行处理,这里直接将数据以json形式存入文本,并且采集文章中的图片

   编辑pipeline.py文件

import json

from scrapy.pipelines.images import ImagesPipeline,FilesPipeline

from scrapy.exceptions import DropItem

import scrapy

import requests

import os

import hashlib

from scrapy.utils.python import to_bytes

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

class TutorialPipeline(object):

def open_spider(self, spider):     # pippeline执行的第一个函数,即将把数据存入items.json文件

self.file = open('items.json', 'w',encoding='utf-8')

def close_spider(self, spider):    # pipeline执行最后一个函数

self.file.close()

#注释内容为用requests下载图片,图片不多但是明显感觉到比框架下载慢的多

def process_item(self, item, spider):   # 执行完成函数,返回item实例

# res = requests.get(item['image_url'][0])

# image_guid = hashlib.sha1(to_bytes(item['image_url'][0])).hexdigest()

# item['image_paths'] = 'images/full/%s.jpg' % image_guid

# if not os.path.exists('images/full/'):

# os.makedirs('images/full/')

# with open(os.path.join(item['image_paths']),'wb') as f:

# f.write(res.content)

line = json.dumps(dict(item))+'\n'

self.file.write(line)

return item

class MyImagePipline(ImagesPipeline):    #使用scarpy的image采集方法

def get_media_requests(self, item, info):   #采集动作,使用item中的图片地址

for image_url in item['image_url']:

# print('>>>>>>>>>>>>>>>>>>>>>')

# print('开始下载图片 '+image_url)

# print(item)

# item['image_paths'] = self.file_path(image_url)

# with open('items_chinaunix.json', 'w',encoding='utf-8') as f:

# f.write(json.dumps(dict(item))+'\n')

yield scrapy.Request(image_url,meta={'item': item})   # 采集动作

def item_completed(self, results, item, info):  # 图片采集完成后执行函数,参数意义查看官网

image_paths = [x['path'] for ok, x in results if ok]

if not image_paths:

raise DropItem("Item contains no images")

item['image_paths'] = image_paths           #  将图片在本地的存储地址加入item

        return item

四.设置settings.py中相关配置

settings.py是针对项目的配置,里面配置相当丰富,具体查看官网

这里只定义几项必须的配置,其他默认

点击(此处)折叠或打开

#设置的pipeline需要在这里启动,每个pipeline处理不同的动作,

后面数字表示优先级,越小优先级越高,不超过1000

ITEM_PIPELINES = {

'demospider.pipelines.MyImagePipline': 300,         

'demospider.pipelines.TutorialPipeline': 301,

}

IMAGES_STORE = 'images'          # 图片存储的路径

五.执行爬虫应用

执行命令     scrapy crawl imagespider       

将会看到执行过程,采集的数据过程,由于数据少,采集过程相当快,不贴截图了,自己练习体会。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/834/viewspace-3126002/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2019-04-12

  • 博文量
    134
  • 访问量
    895