• 初识Scrapy和使用


    初识Scrapy和使用

    了解Scrapy

    Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。 可以应用在包括数据挖掘,信息处理 或存储历史数据等一系列的程序中。

    安装Scrapy

    使用pip直接安装

    Windows:打开cmd,输入 pip install scrapy ,回车。

    pip install scrapy
    

    使用清华镜像

    pip install -i https://pypi.tuna.tsinghua.edu.cn/simple scrapy
    

    其他镜像网址

    清华大学镜像:https://pypi.tuna.tsinghua.edu.cn/simple/

    阿里云:http://mirrors.aliyun.com/pypi/simple/

    中科大镜像:https://pypi.mirrors.ustc.edu.cn/simple/

    豆瓣镜像:http://pypi.douban.com/simple/

    中科大镜像2:http://pypi.mirrors.ustc.edu.cn/simple/

    创建Scrapy项目

     scrapy startproject 项目名称
     --- 例如:scrapy startproject spider_demo01
    

    Scrapy项目构成

     		  spiders 
                  __init__.py
                  自定义的爬虫文件.py       ‐‐‐》由我们自己创建,是实现爬虫核心功能的文件
              __init__.py                  
              items.py                     ‐‐‐》定义数据结构的地方,是一个继承自scrapy.Item的类
              middlewares.py               ‐‐‐》中间件   代理
              pipelines.py  ‐‐‐》管道文件,里面只有一个类,用于处理下载数据的后续处理              
    默认是300优先级,值越小优先级越高(1‐1000)                                        
              settings.py  ‐‐‐》配置文件  比如:是否遵守robots协议,User‐Agent定义等
    

    创建爬虫文件

    scrapy genspider 爬虫名字 网页的域名
    --- 例如:scrapy genspider baidu https://www.baidu.com
    

    运行爬虫文件

    scrapy crawl 爬虫名称
    --- 例如:scrapy crawl baidu
    

    Scrapy的架构组成

    1. 引擎 ‐‐‐》自动运行,无需关注,会自动组织所有的请求对象,分发给下载器

    2. 下载器 ‐‐‐》从引擎处获取到请求对象后,请求数据

    3. spiders ‐‐‐》Spider类定义了如何爬取某个(或某些)网站。包括了爬取的动作(例 如:是否跟进链接)以及如何从网页的内容中提取结构化数据(爬取item)。 换句话说,Spider就是您定义爬取的动作及 分析某个网页(或者是有些网页)的地方。

    4. 调度器 ‐‐‐》有自己的调度规则,无需关注

    5. 管道(Item pipeline) ‐‐‐》最终处理数据的管道,会预留接口供我们处理数据 当ItemSpider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理。 每个item pipeline组件(有时称之为“Item Pipeline”)是实现了简单方法的Python类。他们接收到Item并通过它执行 一些行为,同时也决定此Item是否继续通过pipeline,或是被丢弃而不再进行处理。


      以下是item pipeline的一些典型应用:

      1. 清理HTML数据

      2. 验证爬取的数据(检查item包含某些字段)

      3. 查重(并丢弃)

      4. 将爬取结果保存到数据库中

    Scrapy的工作原理

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    1. 引擎向spidersurl
    2. 引擎将要爬取的url给调度器
    3. 调度器会将url生成请求对象放入到指定的队列中
    4. 从队列中出队一个请求
    5. 引擎将请求交给下载器进行处理
    6. 下载器发送请求获取互联网数据
    7. 下载器将数据返回给引擎
    8. 引擎将数据再次给到spiders
    9. spiders通过xpath解析该数据,得到数据或者url
    10. spiders将数据或者url给到引擎
    11. 引|擎判断该数据还是url,是数据,交给管道(itempipeline)处理,是url交给调度器处理

    相关案例

    PS:相关案例仅用于学习使用!!!

    汽车之家

    # 使用前注释robot协议或者改成False
    import scrapy
    
    class CarSpider(scrapy.Spider):
        name = "car"
        allowed_domains = ["cn.58.com"]
        start_urls = ["https://cn.58.com/dazhong/?PGTID=0d30001d-008d-2709-b9ed-9477389f1bd7"]
    
        def parse(self, response):
            # response.text 字符串
            # content = response.text
            content = response.xpath("//div[@id='list']//img[@class='info_pic']/@data-original")
            for i in content:
                print(i.extract())
    

    当当网

    # 该文件用于读取一些数据,并未做过多的修饰
    import scrapy
    from ..items import SpiderDemo03Item
    
    
    class DangSpider(scrapy.Spider):
        name = "dang"
        allowed_domains = ["category.dangdang.com", "product.dangdang.com"]
        start_urls = ["https://category.dangdang.com/cp01.43.19.00.00.00.html"]
        base_url = 'https://category.dangdang.com/pg'
        page = 1
    
        def parse(self, response):
            li_list = response.xpath("//ul[@id='component_59']/li")
    
            for li in li_list:
                # 第一张图片的src可以使用
                src = li.xpath(".//img/@data-original").extract_first()
                if src:
                    src = src
                else:
                    src = li.xpath(".//img/@src").extract_first()
                name = li.xpath(".//img/@alt").extract_first()
                price = li.xpath(".//p[@class='price']/span[@class='search_now_price']/text()").extract_first()
                book = SpiderDemo03Item(src=src, name=name, price=price)
                # 将数据交给管道文件
                yield book
    
            # https://category.dangdang.com/pg2-cp01.43.19.00.00.00.html
            # 爬取100页
            # if self.page < 100:
            #     self.page += 1
            #     url = self.base_url + str(self.page) + '-cp01.43.19.00.00.00.html'
            #     yield scrapy.Request(url=url, callback=self.parse)
    
    # items.py
    class SpiderDemo03Item(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        src = scrapy.Field()
        name = scrapy.Field()
        price = scrapy.Field()
        time = scrapy.Field()
    
    # pipelines.py
    import urllib.request
    
    class SpiderDemo03Pipeline:
        # 打开文件
        def open_spider(self, spider):
            self.fp = open('dang.json', 'w', encoding='utf-8')
    
        def process_item(self, item, spider):
            # 写入到json文件
            self.fp.write(str(item))
    
            return item
    
        # 关闭文件
        def close_spider(self, spider):
            self.fp.close()
    
    
    # 多管道下载
    # 记得在当前目录下面添加books文件夹
    class dangPipeline:
        def process_item(self, item, spider):
            url = 'http:'+item.get('src')
            filename = './books/' + item.get('name') + '.jpg'
            urllib.request.urlretrieve(url, filename)
            return item
    
    # settings.py
    # 需要添加下图的管道解开注释即可
    ITEM_PIPELINES = {
       # 下载图片的管道
       # "spider_demo03.pipelines.dangPipeline": 301,
       # 保存json文件的管道
       "spider_demo03.pipelines.SpiderDemo03Pipeline": 300,
    }
    

    CrawlSpider

    CrawlSpider可以定义规则,再解析html内容的时候,可以根据链接规则提取出指定的链接,然后再向这些链接发 送请求

    所以,如果有需要跟进链接的需求,意思就是爬取了网页之后,需要提取链接再次爬取,使用CrawlSpider是非常 合适的

    案例:读书网数据入库

    创建项目:

    scrapy startproject spider_demo
    

    创建爬虫类:

    scrapy genspider ‐t crawl read www.dushu.com
    

    配置数据库:

    # settings.py
    DB_HOST = 'localhost'
    DB_PORT = 3306
    DB_USER = 'root'
    DB_PASSWORD = '123456'
    DB_NAME = 'spider'
    DB_CHARSET = 'utf8'
    
    # 关闭robot协议
    ROBOTSTXT_OBEY = False
    
    # 开启日志输出文件,可以不选择开启
    LOG_FILE = "log.log"
    

    编写爬虫类文件:

    import scrapy
    from scrapy.linkextractors import LinkExtractor
    from scrapy.spiders import CrawlSpider, Rule
    from ..items import SpiderDemo04Item
    
    
    class ReadSpider(CrawlSpider):
        name = "read"
        allowed_domains = ["www.dushu.com"]
        start_urls = ["https://www.dushu.com/book/1617_1.html"]
    
        # 这里需要编写匹配的html地址,可以去官网参考
        rules = (
            Rule(LinkExtractor(
                allow=r"/book/1617_\d+"),
                callback="parse_item",
                follow=True),
        )
    
        def parse_item(self, response):
            img_list = response.xpath("//div[@class='book-info']//a/img")
            for i in img_list:
                src = i.xpath("./@data-original").extract_first()
                name = i.xpath("./@alt").extract_first()
                book = SpiderDemo04Item(name=name, src=src)
                yield book
    
    # items.py
    class SpiderDemo04Item(scrapy.Item):
        # define the fields for your item here like:
        name = scrapy.Field()
        src = scrapy.Field()
    

    编写管道文件:

    # 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
    # 加载配置文件
    from scrapy.utils.project import get_project_settings
    import pymysql
    
    
    class SpiderDemo04Pipeline:
        def open_spider(self, spider):
            self.fp = open('dushu.json', 'w', encoding='utf-8')
    
        def process_item(self, item, spider):
            self.fp.write(str(item))
            return item
    
        def close_spider(self, spider):
            self.fp.close()
    
    
    class MysqlPipeline:
        # 链接MySQL
        def open_spider(self, spider):
            settings = get_project_settings()
            self.conn = pymysql.connect(
                host=settings['DB_HOST'],
                port=settings['DB_PORT'],
                user=settings['DB_USER'],
                password=settings['DB_PASSWORD'],
                database=settings['DB_NAME'],
                charset=settings['DB_CHARSET']
            )
            self.cursor = self.conn.cursor()
            print('链接数据库成功')
    
        def process_item(self, item, spider):
            sql = 'insert into book(name,src) values(%s,%s)'
            self.cursor.execute(sql, (item['name'], item['src']))
            self.conn.commit()
            return item
    
        # 关闭链接
        def close_spider(self, spider):
            self.cursor.close()
            self.conn.close()
            print('关闭数据库链接')
    

    记得在配置文件打开管道:

    ITEM_PIPELINES = {
        "spider_demo04.pipelines.MysqlPipeline": 301,
        "spider_demo04.pipelines.SpiderDemo04Pipeline": 300,
    }
    

    Scrapy的post请求

    import scrapy
    import json
    
    
    class DushuSpider(scrapy.Spider):
        name = "dushu"
        allowed_domains = ["fanyi.baidu.com"]
        start_urls = ["https://fanyi.baidu.com/sug/"]
    
        # 需要使用功能 start_requests 方法
        def start_requests(self):
            url = "https://fanyi.baidu.com/sug/"
            data = {
                "kw": "hello"
            }
            yield scrapy.FormRequest(url=url, formdata=data, callback=self.parse_second)
    
        def parse_second(self, response):
            content = response.text
            obj = json.loads(content)
            print(obj)
    

    代理

    1. settings.py中,打开一个选项
    DOWNLOADER_MIDDLEWARES = { 
        'postproject.middlewares.Proxy': 543, 
    } 
    
    1. middlewares.py中写代码
    def process_request(self, request, spider): 
        request.meta['proxy'] = 'https://113.68.202.10:9999' 
        return None
    
  • 相关阅读:
    云扩RPA携手中联教育引领财务机器人教学创新
    Web2 vs. Web3,社交工具的发展会有什么变化?
    智能化测试探索
    linux安装mysql8超详细到每步命令
    Vue:实战快速上手
    剑指YOLOv7改进最新重参数化结构RepViT| 最新开源移动端网络架构ICCV 2023,1.3ms 延迟,速度贼快
    你知道npm、yarn、pnpm的区别吗?
    14-RPC-自研微服务框架
    快手治理低质量直播内容,运营者需要注意什么?
    37 深度学习(一):查看自己显卡的指令|张量|验证集|分类问题|回归问题
  • 原文地址:https://blog.csdn.net/The_more_more/article/details/139863875