爬虫之scrapy使用(八)

1、说明

  • 创建一个工程:scrapy startproject xxxPro
  • cd xxxPro
  • 在spiders子目录中创建一个爬虫文件
    • scrapy genspider spiderName www.xxx.com
  • 执行工程:
    • scrapy crawl spiderName

scrapy的五大核心组件:

组件介绍
引擎(Scrapy)用来处理整个系统的数据流处理, 触发事务(框架核心)
调度器(Scheduler)用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址
下载器(Downloader)用于下载网页内容, 并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
爬虫(Spiders)爬虫是主要干活的, 用于从特定的网页中提取自己需要的信息, 即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
项目管道(Pipeline)负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。

2、站长图片爬取

图片地址

#创建scrapy项目和爬虫文件
scrpay startproject imgpro
cd imgpro
scrapy genspider img
#系统自动生成xiaoh.py爬虫文件

1、对img.py文件编写,实现网页的爬取和数据解析。

import scrapy
from imgpro.items import ImgproItem

class ImgSpider(scrapy.Spider):
    name = 'img'
    # allowed_domains = ['ww']
    start_urls = ['http://sc.chinaz.com/tupian/']
    base_url = 'http://sc.chinaz.com/tupian/index_%d.html'
    page_num = 2	#分页标记页

    def parse(self, response):
    	#获取当前页面所有图片dix标签
        div_list = response.xpath('//div[@id="container"]/div')
        for div in div_list:
        	#对每张图片进行src和名称爬取
            src = div.xpath('./div/a/img/@src2').extract_first()
            name = div.xpath('./p/a/text()').extract()[0]
            name = str(''.join(name)).replace('图片', '') + '.jpg'
            #导入框架中的ImgproItem类,在ImgproItem添加name和src属性,在items.py脚本中
            #src = scrapy.Field()
 			#name = scrapy.Field()
            item = ImgproItem()
            item['src'] = src
            item['name'] = name
            yield item	#在整个项目当中就能使用item
        #开始分页
        if self.page_num <= 200:
            print('第%d页爬取成功!!!' % (self.page_num))
            #拼接下一页的url
            new_url = format(self.base_url % self.page_num)
            self.page_num += 1
            #Request传入新的url和callback回调解析方法
            yield scrapy.Request(new_url, callback=self.parse)

2、在pipelines.py中可以对获取的数据进行持久化储存,对于图片,scrapy有特定的类来实现储存。

from scrapy.pipelines.images import ImagesPipeline
import scrapy
class imgsPileLine(ImagesPipeline):

    #就是可以根据图片地址进行图片数据的请求
    def get_media_requests(self, item, info):
		#使用meta来传参
        yield scrapy.Request(item['src'], meta={'item':item})

    #指定图片存储的路径
    def file_path(self, request, response=None, info=None):
        imgName = request.meta['item']['name']
        return imgName

    def item_completed(self, results, item, info):
        return item #返回给下一个即将被执行的管道类
        

3、到这里我们的代码就已经编写好了,但是需要对项目进行设置,在settings.py文件中。

#UA伪装
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
ROBOTSTXT_OBEY = False
#只打印错误的信息
LOG_LEVEL = 'ERROR'
#开启imgsPileLine管道
ITEM_PIPELINES = {
   'imgpro.pipelines.imgsPileLine': 300,
}
#图片储存的路径
IMAGES_STORE = './img_zhx'

然后就直接scrapy crawl img就可以运行了。

3、中间件的使用(网易新闻)

网易新闻实例只爬取了国内和国外两栏的新闻。
在这里插入图片描述
因为网易云新闻的数据是动态加载出来的,所以我们使用了selenium来进行动态化的爬取。

1、对wangyi.py文件编写,实现网页的爬取和数据解析。

import scrapy
from wangyiPro.items import WangyiproItem
from selenium import webdriver

class WangyiSpider(scrapy.Spider):
    name = 'wangyi'
    # allowed_domains = ['news.163.com']
    start_urls = ['http://news.163.com/']
    li_url_list = []

    def __init__(self):
        self.bro = webdriver.Chrome(executable_path='D:\workspace\chromedriver.exe')

    def parse(self, response):
        wangyi_list = [6, 7]
        li_list = response.xpath('//*[@id="index2016_wrap"]/div[1]/div[2]/div[2]/div[2]/div[2]/div/ul/li')
        for index in wangyi_list:
            li_url = li_list[index].xpath('./a/@href').extract_first()
            print(li_url)
            self.li_url_list.append(li_url)

            # 依次对每一个板块对应的页面进行请求
        for url in self.li_url_list:  # 对每一个板块的url进行请求发送
            yield scrapy.Request(url, callback=self.parse_model)


    def parse_model(self, response):
        div_list = response.xpath('/html/body/div[1]/div[3]/div[4]/div[1]/div/div/ul/li/div/div')
        for div in div_list:
            title = div.xpath('./div/h3/a/text() | ./div/div[1]/h3/a/text()').extract_first()
            new_detial_url = div.xpath('./div/h3/a/@href | ./div/div[1]/h3/a/@href').extract_first()
            if title == None:
                continue
            print(title, new_detial_url)
            item = WangyiproItem()
            item['title'] = title
            yield scrapy.Request(url=new_detial_url, callback=self.parse_detail, meta={'item': item})

    def parse_detail(self, response):
        # p_list = response.xpath('//*[@id="endText"]/p')
        # content_list = []
        # for p in p_list:
        #     p_text = p.xpath('./text()').extract_first()
        #     content_list.append(p_text)
        # content = ''.join('%s' %id for id in content_list)
        # item = response.meta['item']
        # item['content'] = content
        content = response.xpath('//*[@id="endText"]//text()').extract()
        content = ''.join(content)
        item = response.meta['item']
        item['content'] = content
        yield item

    def closed(self, spider):
        self.bro.quit()

2、在pipelines.py中可以对获取的数据进行持久化储存,对于图片,scrapy有特定的类来实现储存。

from itemadapter import ItemAdapter

class WangyiproPipeline:
    fp = None
    def open_spider(self, spider):
        print('开始爬虫')
        self.fp = open('./wangyi.txt', 'w', encoding='utf-8')

    # 处理item,接受一次调用一次
    def process_item(self, item, spider):
        title = item['title']
        content = item['content']
        self.fp.write(title + ':' + content + '\n'+'*'*100+'\n')
        return item

    def close_spider(self, spider):
        print('爬虫结束!!')
        self.fp.close()

3、主要是使用下载中间件的process_response方法。

#该方法拦截五大板块对应的响应对象,进行篡改
    def process_response(self, request, response, spider):#spider爬虫对象
        bro = spider.bro#获取了在爬虫类中定义的浏览器对象
        #挑选出指定的响应对象进行篡改
        #通过url指定request
        #通过request指定response
        if request.url in spider.models_urls:
            bro.get(request.url) #五个板块对应的url进行请求
            sleep(3)
            page_text = bro.page_source  #包含了动态加载的新闻数据

            #response #五大板块对应的响应对象
            #针对定位到的这些response进行篡改
            #实例化一个新的响应对象(符合需求:包含动态加载出的新闻数据),替代原来旧的响应对象
            #如何获取动态加载出的新闻数据?
                #基于selenium便捷的获取动态加载数据
            new_response = HtmlResponse(url=request.url,body=page_text,encoding='utf-8',request=request)
            return new_response
        else:
            #response #其他请求对应的响应对象
            return response

4、到这里我们的代码就已经编写好了,但是需要对项目进行设置,在settings.py文件中。

#UA伪装
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
ROBOTSTXT_OBEY = False
#只打印错误的信息
LOG_LEVEL = 'ERROR'
#开启WangyiproPipeline管道
ITEM_PIPELINES = {
   'wangyiPro.pipelines.WangyiproPipeline': 300,
}

#开启下载中间件
DOWNLOADER_MIDDLEWARES = {
   'wangyiPro.middlewares.WangyiproDownloaderMiddleware': 543,
}

然后就直接scrapy crawl wangyi就可以运行了。

项目1GitHub
项目2GitHub

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值