python爬虫–scrapy(再探)

python爬虫–scrapy(再探)

python爬虫–scrapy(再探)

scrapy项目创建

请移步这里

基于scrapy的全站数据爬取

—需求:爬取校花网中全部图片的名称

http://www.521609.com/meinvxiaohua/

实现方式:

  • 将所有页面的ur L添加到start_ urls列表(不推荐)

  • 自行手动进行请求发送(推荐)

    手动请求发送: yield scrapy. Request (url, callback) : callback专用做于数据解析

创建scrapy以及基于管道的持久化存储:请点击此处查看

import scrapy
from meinvNetwork.items import MeinvnetworkItem

class MnspiderSpider(scrapy.Spider):
    name = 'mnSpider'
    #allowed_domains = ['www.xxx.com']
    start_urls = ['http://www.521609.com/meinvxiaohua/']
    url = 'http://www.521609.com/meinvxiaohua/list12%d.html'
    page_num = 2
    def parse(self, response):
        li_list = response.xpath('//*[@id="content"]/div[2]/div[2]/ul/li')
        for li in li_list:
            name = li.xpath('./a[2]/b/text() | ./a[2]/text()').extract_first()
            item = MeinvnetworkItem(name=name)
            yield item
        if self.page_num <= 11:
            new_url = format(self.url%self.page_num)
            self.page_num += 1
            yield scrapy.Request(url=new_url,callback=self.parse)

使用终端命令执行项目:scrapy crawl mnSpider
效果图
在这里插入图片描述
在这里插入图片描述

五大核心组件

在这里插入图片描述

引擎(Scrapy)

  • 用来处理整个系统的数据流处理,触发事务(框架核心)

调度器(Scheduler)

  • 用来接收引擎发过来的请求,压入队列中,并在引擎再次请求的时候返回。可以想象成一个URL(抓取网页的网址或者说是链接)的优先队列,由他来决定下一个要抓取的网址是什么,同时去除重复的网址。

下载器(DownLoader)

  • 用于下载网页内容,并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个搞笑的异步模型上的)

爬虫(spiders)

  • 爬虫是主要干活的,用于从特定的网页中提取自己需要的信息,即所谓的实体(Item)。用户也可以从中提取出链接,让Scrapy继续抓取下一个页面。

项目管道(Pipeline)

  • 负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体,验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管理,并经过几个特定的持续处理数据。

请求传参

使用场景:如果爬取解析的数据不在同一张页面中。(深度爬取)

详见案例:爬取网易新闻

scrapy图片爬取

图片数据爬取(ImagesPipeline)

基于scrapy爬取字符串类型的数据和爬取图片类型的数据区别

— 字符串:只需要基于小path进行解析且提交管道进行持久化存储

— 图片:xpath解析出图片src的属性值。单独的对图片地址发起请求获取图片二进制类型的数据。

使用流程:

— 数据解析(图片地址)

— 将存储图片地址的item提交到指定的管道类

— 在管道文件中自制一个机遇ImagesPipeline的管道类

​		— def get_media_requests(self,item,info):#根据图片地址进行数据请求

​		— def file_path(self,request,response=None,info=None):#指定图片存储类型

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

— 在配置文件中:

​		— 指定图片存储的目录:IMAGES_STORE = './img_temp'

​		— 指定开启的管道:自制定的管道类

目录层级

在这里插入图片描述

img.py

import scrapy
from imgsPro.items import ImgsproItem

class ImgSpider(scrapy.Spider):
    name = 'img'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://sc.chinaz.com/tupian/']

    def parse(self, response):
        div_list = response.xpath('//div[@id="container"]/div')
        for div in div_list:
            #注意伪属性
            img_url = 'https:' + div.xpath('./div/a/img/@src2').extract()[0]
            item = ImgsproItem(img_url=img_url)
            yield item

items.py

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class ImgsproItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    img_url = scrapy.Field()
    #pass

pipeline.py

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
from itemadapter import ItemAdapter


# class ImgsproPipeline:
# def process_item(self, item, spider):
# return item
from scrapy.pipelines.images import ImagesPipeline
import scrapy

class imgsPipeLine(ImagesPipeline):
    #根据图片地址进行数据请求
    def get_media_requests(self,item,info):

        yield scrapy.Request(item['img_url'])
    #指定图片存储类型
    def file_path(self,request,response=None,info=None):
        imgName = request.url.split('/')[-1]
        return imgName

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

setting.py


BOT_NAME = 'imgsPro'

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

LOG_LEVEL = 'ERROR'
# Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT = 'imgsPro (+http://www.yourdomain.com)'
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'
# Obey robots.txt rules
ROBOTSTXT_OBEY = False


# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
   
   'imgsPro.pipelines.imgsPipeLine': 300,
}

#指定图片存储路径
IMAGES_STORE = './img_temp'

效果图

在这里插入图片描述

中间件的使用

下载中间件

  • 位置:引擎和下载器之间
  • 作用:批量拦截到整个工程中的所有请求和响应
  • 拦截请求:
    • UA伪装
    • 代理IP
  • 拦截响应:篡改响应数据,响应对象。

中间件案例:网易新闻

https://news.163.com/

需求:爬取网易新闻中的新闻数据(标题和内容)

  • 1.通过网易新闻的首页解析出五大板块对应的详情页的url (没有动态加载)
  • 2.每一个板块对应的新闻标题都是动态加载出来的(动态加载)
  • 3.通过解析出每一条新闻详情页的url获取详情页的页面源码,解析出新闻内容

目录层级
在这里插入图片描述

wangyi.py

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

class WangyiSpider(scrapy.Spider):
    name = 'wangyi'
    # allowed_domains = ['www.xxx.com']
    start_urls = ['https://news.163.com/']
    model_urls = []
    def __init__(self):
        self.bro = webdriver.Chrome(executable_path=r"E:\google\Chrome\Application\chromedriver.exe")
    def parse(self, response):
        li_list = response.xpath('//*[@id="index2016_wrap"]/div[1]/div[2]/div[2]/div[2]/div[2]/div/ul/li')
        alist = [3,4,6,7,8]
        for i in alist:
            model_url = li_list[i].xpath('./a/@href').extract_first()
            self.model_urls.append(model_url)
        for url in self.model_urls:
            yield scrapy.Request(url,callback=self.model_parse)

    def model_parse(self,response):
        div_list = response.xpath('/html/body/div/div[3]/div[4]/div[1]/div[1]/div/ul/li/div/div')
        for div in div_list:
            title = div.xpath('./div/div[1]/h3/a/text()').extract_first()
            new_detail_url = div.xpath('./div/div[1]/h3/a/@href').extract_first()
            if new_detail_url == None:
                continue
            item = WangyiproItem()
            item['title'] = title
            yield scrapy.Request(url=new_detail_url,callback=self.parse_detail,meta={
   'item':item})
    def parse_detail(self,response):
        content = response.xpath('//*[@id="content"]/div[2]//text()').extract()
        content = ''.join(content)
        item = response.meta['item']
        item['content'] = content
        yield item

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


items.py

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class WangyiproItem(scrapy.Item):
    # define the fields for your item here like:
    title = scrapy.Field()
    content = scrapy.Field()

middlewares.py

# Define here the models for your spider middleware
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/spider-middleware.html

from scrapy import signals

# useful for handling different item types with a single interface
from itemadapter import is_item, ItemAdapter
from scrapy.http import HtmlResponse
from time import sleep


class WangyiproDownloaderMiddleware:
    # Not all methods need to be defined. If a method is not defined,
    # scrapy acts as if the downloader middleware does not modify the
    # passed objects.



    def process_request(self, request, spider):
        # Called for each request that goes through the downloader
        # middleware.

        # Must either:
        # - return None: continue processing this request
        # - or return a Response object
        # - or return a Request object
        # - or raise IgnoreRequest: process_exception() methods of
        # installed downloader middleware will be called
        return None

    def process_response(self, request, response, spider):
        bro = spider.bro
        if request.url in spider.model_urls:
            bro.get(request.url)
            sleep(2)
            page_text = bro.page_source
            new_response = HtmlResponse(url=request.url,body=page_text,encoding='utf-8',request=request)
            return new_response
        else:

            return response

    def process_exception(self, request, exception, spider):
        # Called when a download handler or a process_request()
        # (from other downloader middleware) raises an exception.

        # Must either:
        # - return None: continue processing this exception
        # - return a Response object: stops process_exception() chain
        # - return a Request object: stops process_exception() chain
        pass


pipelines.py

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
from itemadapter import ItemAdapter


class WangyiproPipeline:
    fp = None

    # 重写父类的一个方法:该方法只在爬虫开始的时候被调用一次
    def open_spider(self, spider):
        print('开始爬虫。。。。')
        self.fp = open('./wangyi.txt', 'w', encoding='utf-8')

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

    def process_item(self, item, spider):
        title = item['title']
        content = item['content']
        self.fp.write(title+content + '\n')
        return item

setting.py

BOT_NAME = 'wangyiPro'

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


# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11'
LOG_LEVEL = 'ERROR'
# Obey robots.txt rules
ROBOTSTXT_OBEY = False


# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
DOWNLOADER_MIDDLEWARES = {
   
   'wangyiPro.middlewares.WangyiproDownloaderMiddleware': 543,
}

# Enable or disable extensions
# See https://docs.scrapy.org/en/latest/topics/extensions.html
#EXTENSIONS = {
   
# 'scrapy.extensions.telnet.TelnetConsole': None,
#}

# Configure item pipelines
# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
   
   'wangyiPro.pipelines.WangyiproPipeline': 300,
}

效果图
在这里插入图片描述

CrawlSpider的全站数据爬取

CrawlSpider是Spider的一个子类
全站数据爬取方式:

  1. 基于Spider:手动请求
  2. 基于CrawlSpider:

CrawlSpider的使用:

  • 创建一个工程

cd XXX

  • 创建爬虫文件(CrawlSpider) :

scrapy genspider -t crawl xxx www.xxx.com

  • 链接提取器:
    • 作用:根据指定的规则(allow) 进行指定链接的提取
  • 规则解析器:
    • 作用:将链接提取器提取到的链接进行指定规则(callback) 的解析

例子:

http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1

sun.py

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


class SunSpider(CrawlSpider):
    name = 'sun'
    #allowed_domains = ['www.xxx.com']
    start_urls = ['http://wz.sun0769.com/political/index/politicsNewest?id=1&page=1']
    link = LinkExtractor(allow=r'id=1&page=\d+')
    rules = (
        Rule(link, callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        item = {
   }
        #item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
        #item['name'] = response.xpath('//div[@id="name"]').get()
        #item['description'] = response.xpath('//div[@id="description"]').get()
        #return item
        print(response)

因为该网站更新技术,所以只能显示10页的数据(IP惨遭封禁)
在这里插入图片描述
在这里插入图片描述
还在学习,目前解决不了

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/100088.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • vue 实现父子组件传值和子父组件传值

    vue 实现父子组件传值和子父组件传值先上一张图,vue父子组件传值都用的图片。从张图入手了解如何传参。一、父组件1.引入子组件importrandomfrom”./child-random-paper”;2.注册子组件components:{random,},3.静态组件,循环体<liv-for=”(item,index)inselectedTypeQuestion”:key=”item.id”:ind…

  • jsp延时跳转_js自动跳转到指定页面

    jsp延时跳转_js自动跳转到指定页面本文仅供学习交流使用,如侵立删!联系方式及demo下载见文末js延时页面跳转<scripttype=”text/javascript”> functionsend(){ alert(“转账码制作成功!!!”); window.history.back();//返回上一页 } setTimeout(send,2000);//等待2秒后执行</script>本文仅供学习交流使用,如侵立删!企鹅、WX:1033383881…

  • JS学习笔记-OO创建怀疑的对象

    JS学习笔记-OO创建怀疑的对象

  • c语言s16与u16_c语言中u8和u16是啥

    c语言s16与u16_c语言中u8和u16是啥在C语言中,并没有U16和S16这两种基本类型。不过在C语言的编程习惯上,往往为了简写,约定U16和S16两种类型。尤其常见于嵌入式编程或驱动编程上。其中U16为16位无符号数,S16为16为有符号数。定义如下:typedefshortS16;typedefunsignedshortU16;可以看到,U16和S16都是占2个字节的整型类型,区别只是是否有符号。于是U16可…

  • servlet异步请求

    servlet异步请求1、什么是servlet异步请求Servlet3.0之前,一个普通Servlet的主要工作流程大致如下:(1)、Servlet接收到请求之后,可能需要对请求携带的数据进行一些预处理;(2)、调用业务接口的某些方法,以完成业务处理;(3)、根据处理的结果提交响应,Servlet线程结束。其中第二步处理业务逻辑时候很可以碰到比较耗时的任务,此时servlet主线程会阻塞等待完成业务处理,对于并发比较大的请求可能会产生性能瓶颈,则servlet3.0之后再此处做了调整,引入了…

  • java定义数组_java中数组的三种定义方式_java中数组的定义及使用方法(推荐)…

    java定义数组_java中数组的三种定义方式_java中数组的定义及使用方法(推荐)…描述java中数组的三种定义方式java中,数组是一种很常用的工具,今天我们来说说数组怎么定义[java]viewplaincopy/***数组的三种定义方法*1.数组类型[]数组名=new数组类型[数组长度];*2.数组类型[]数组名={数组0,数组1,数组2,数组3,。。。。};*3.数组类型[]数组名=new数组类型[]{数组0,数组1,数组2,。。。};**/p…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号