ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

scrapy的使用

2022-05-11 23:03:29  阅读:160  来源: 互联网

标签:xpath cnblogs self 爬虫 item scrapy 使用


scrapy架构和目录介绍

# pip3 install scrapy
# 创建项目:scrapy startproject cnblogs_spider   等同于django创建项目
# 创建爬虫:scrapy genspider cnblogs www.cnblogs.com   等同于创建app
    -本质就是在spiders文件夹下创建一个py文件,写入一些代码
# 运行爬虫:scrapy crawl 爬虫名

项目目录介绍

cnblogs_spider   # 项目名字
    -cnblogs_spider # 文件夹
    -spiders      # 文件夹,下面放了一个个爬虫文件
        -cnblogs.py  # 一个个的爬虫文件
    items.py       # 模型类写了一些字段---》类似于django的models
    middlewares.py # 中间件:爬虫中间件和下载中间件
    pipelines.py   # 管道:存储数据的代码写在这
    settings.py    # 项目的配置文件
  scrapy.cfg       # 项目上线需要用到,不用管
  
  
  
# 重点:咱们以后主要是在cnblogs.py爬虫文件中写爬取和解析的逻辑,pipelines写存储

scrapy架构

# 引擎(EGINE)-->大总管,负责全部的数据流向--》内置的,咱们不需要写

引擎负责控制系统所有组件之间的数据流,并在某些动作发生时触发事件。

# 调度器(SCHEDULER)---》对要爬取的地址进行排队,去重
用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL的优先级队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址

# 下载器(DOWLOADER)--》真正负责下载---》高效的异步模型
用于下载网页内容, 并将网页内容返回给EGINE,下载器是建立在twisted这个高效的异步模型上的

# 爬虫(SPIDERS)--》咱们重点写的地方,解析响应,从响应中提取要保存的数据和下一次爬取的地址
SPIDERS是开发人员自定义的类,用来解析responses,并且提取items,或者发送新的请求

# 项目管道(ITEM PIPLINES)---》存储数据的逻辑---》可以存到文件,redis,mysql。。。
在items被提取后负责处理它们,主要包括清理、验证、持久化(比如存到数据库)等操作

# 下载器中间件(Downloader Middlewares)--》用的多
位于Scrapy引擎和下载器之间,主要用来处理从EGINE传到DOWLOADER的请求request(加请求头,加cookie,加代理),已经从DOWNLOADER传到EGINE的响应response进行一些处理

# 爬虫中间件(Spider Middlewares)---》用的少
位于EGINE和SPIDERS之间,主要工作是处理SPIDERS的输入(即responses)和输出(即requests)

 

 py文件直接运行爬虫

# 右键运行它就可以运行爬虫,不需要每次都敲命令

from scrapy import cmdline

# cmdline.execute(['scrapy', 'crawl' ,'cnblogs','--nolog'])
cmdline.execute(['scrapy', 'crawl' ,'cnblogs'])

 

scrapy解析数据

###################################  重点
1 response对象有css方法和xpath方法
    -css中写css选择器
  -xpath中写xpath选择
2 重点1:
    -xpath取文本内容
        './/a[contains(@class,"link-title")]/text()'
   -xpath取属性
    './/a[contains(@class,"link-title")]/@href'
   -css取文本
    'a.link-title::text'
   -css取属性
    'img.image-scale::attr(src)'
3 重点2:
    .extract_first()  取一个
  .extract()       取所有

setting相关配置

# 两套配置,内置一套,用户一套


ROBOTSTXT_OBEY = False  # 是否遵循爬虫协议,如果写了它,一般网站都不让爬,基本写成false
USER_AGENT = '浏览器头' # 爬虫请求头中USER_AGENT是什么,做成浏览器的样子
LOG_LEVEL='ERROR'  # 日志级别改成ERROR,以后错误日志会打印,普通日志不打印
#---------#####-------
SPIDER_MIDDLEWARES=[]      # 爬虫中间件,可以写多个
DOWNLOADER_MIDDLEWARES=[]  # 下载中间件类,配置在这,可以配多个
ITEM_PIPELINES=[]          # 保存数据,会执行到的类,类内部写保存逻辑

提高爬虫效率配置

#1 增加并发:
默认scrapy开启的并发线程为32个,可以适当进行增加。在settings配置文件中修改CONCURRENT_REQUESTS = 100值为100,并发设置成了为100。
#2 降低日志级别:
在运行scrapy时,会有大量日志信息的输出,为了减少CPU的使用率。可以设置log输出信息为INFO或者ERROR即可。在配置文件中编写:LOG_LEVEL = 'INFO'

# 3 禁止cookie:
如果不是真的需要cookie,则在scrapy爬取数据时可以禁止cookie从而减少CPU的使用率,提升爬取效率。在配置文件中编写:COOKIES_ENABLED = False
# 4 禁止重试:
对失败的HTTP进行重新请求(重试)会减慢爬取速度,因此可以禁止重试。在配置文件中编写:RETRY_ENABLED = False
# 5 减少下载超时:
如果对一个非常慢的链接进行爬取,减少下载超时可以能让卡住的链接快速被放弃,从而提升效率。在配置文件中进行编写:DOWNLOAD_TIMEOUT = 10 超时时间为10s

 

全站爬取cnblogs文章

import scrapy
from cnblogs_spider.items import CnblogsSpiderItem
from scrapy.http import Request


class CnblogsSpider(scrapy.Spider):
    name = 'cnblogs'
    allowed_domains = ['www.cnblogs.com']
    start_urls = ['http://www.cnblogs.com/']

    def parse(self, response):
        res = response.text
        article_list = response.xpath('//*[@id="post_list"]/article[@class="post-item"]')
        for article in article_list:
            item = CnblogsSpiderItem()
            title = article.xpath('./section/div/a/text()').extract_first()
            descriptive = article.xpath('./section/div/p/text()').extract()[0].replace('\n', '').replace(' ', '')
            if not descriptive:
                descriptive = article.xpath('./section/div/p/text()').extract()[1].replace('\n', '').replace(' ', '')
            img = article.xpath('./section/div/p/a/img/@src').extract_first()
            name = article.xpath('./section/footer/a/span/text()').extract_first()
            detail_url = article.xpath('./section/div/a/@href').extract_first()
            item['title'] = title  # 不能使用 . 赋值,必须用 [] 赋值
            item['descriptive'] = descriptive  # 不能使用 . 赋值,必须用 [] 赋值
            item['name'] = name  # 不能使用 . 赋值,必须用 [] 赋值
            item['img'] = img  # 不能使用 . 赋值,必须用 [] 赋值

            yield Request(url=detail_url, callback=self.parse_detail, meta={'item': item})

        # 爬取文章列表页的下一页
        next_url = 'https://www.cnblogs.com' + response.xpath(
            '//*[@id="paging_block"]/div/a[last()]/@href').extract_first()
        # next_url='https://www.cnblogs.com'+response.css('#paging_block > div > a:last-child::attr(href)').extract_first()
        print(next_url)
        # 继续爬取下一页,再爬完,解析方式还是这个解析方式
        yield Request(url=next_url)


    def parse_detail(self, response):
        # 解析出文章详情--》如何对上之前的文章标题,摘要。。。
        item = response.meta.get('item')
        detail = str(response.css('#cnblogs_post_body').extract_first())
        item['detail'] = detail
        yield item  # 触发pipline,走存储

item.py

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

import scrapy


class CnblogsSpiderItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    title = scrapy.Field()
    img = scrapy.Field()
    name = scrapy.Field()
    descriptive = scrapy.Field()
    detail_url = scrapy.Field()
    detail = scrapy.Field()

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
import pymysql

class CnblogsSpiderPipeline:
    # 所有的保存都用一个连接,最后存完把连接关闭,爬虫一启动打开数据库连接,爬虫关闭,关闭数据库连接

    def open_spider(self,spider):
        print("我开了")
        self.conn = pymysql.connect(
            user='root',
            password="456",
            host='127.0.0.1',
            database='cnblogs',
            port=3306,
            autocommit=True  # 自动提交
        )
        self.cursor = self.conn.cursor()
    def process_item(self, item, spider):
        # 每个文章都会一次次的触发该方法的执行,在这里写保存逻辑
        print('pipline:', item['title'])
        self.cursor.execute('insert into article (title,descriptive,detail,name,img) values (%s,%s,%s,%s,%s)',
                       args=[item['title'], item['descriptive'], item['detail'], item['name'], item['img'], ])

        return item

    def close_spider(self,spider):
        print('我关了')
        self.cursor.close()
        self.conn.close()

 

加代理,加header,集成selenium

0 在下载中间件的process_reqeust方法中
1 加cookie
    # request.cookies['name']='lqz'
    # request.cookies= {}
2 修改header
      # request.headers['Auth']='asdfasdfasdfasdf'
      # request.headers['USER-AGENT']='ssss'
3 加代理
      request.meta['proxy']='http://103.130.172.34:8080'
    
    
4 fake_useragent模块,可以随机生成user-aget
        from fake_useragent import UserAgent
        ua = UserAgent()
        print(ua.ie)   #随机打印ie浏览器任意版本
        print(ua.firefox) #随机打印firefox浏览器任意版本
        print(ua.chrome)  #随机打印chrome浏览器任意版本
        print(ua.random)  #随机打印任意厂家的浏览器 

 

标签:xpath,cnblogs,self,爬虫,item,scrapy,使用
来源: https://www.cnblogs.com/892572624A/p/16260333.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有