【Python爬虫】爬虫框架Scrapy初使用_爬取4399游戏页面数据

发布时间 2023-12-12 17:49:23作者: 小C学安全

Scrapy简介

Scrapy 是一个用于爬取和提取数据的开源web抓取框架。它提供了一个强大的机制,让开发者可以轻松地创建和管理爬虫程序,以从网站上自动提取结构化的数据。
以下是Scrapy的一些主要特点和优势:

  • 强大灵活的爬取能力:Scrapy具有高度可配置的请求处理和数据提取功能。它可以轻松地处理包括JavaScript渲染页面、登录验证、代理设置等在内的复杂爬取场景。
  • 高效的异步处理:Scrapy采用异步非阻塞的方式进行网络请求和数据处理,能够高效地处理大规模的请求和并发。
  • 分布式支持:Scrapy可以通过分布式的方式进行爬取,让多个爬虫实例同时工作,提高爬取效率。
  • 内置的数据提取工具:Scrapy提供了强大的选择器(Selector)和XPath等工具,用于方便地从页面中提取结构化的数据。
  • 中间件和拓展性:Scrapy的中间件机制使得对请求和响应进行自定义处理变得简单。它还提供了丰富的拓展接口,方便开发者根据自己的需求进行扩展和定制。
  • 内置的调试工具:Scrapy提供了方便的日志记录和调试工具,帮助开发者定位和解决爬取中的问题。
  • 文档丰富,活跃的社区支持:Scrapy拥有完善的文档和活跃的社区支持,您可以轻松地找到大量的教程、示例和解答问题的资源。

总之,Scrapy是一个功能强大、灵活可配置的Web抓取框架,适用于各种规模的爬取任务。它可以帮助开发者高效地构建和管理爬虫,提取所需的数据,并支持大规模的并发和分布式爬取。

Scrapy使用流程

  1. 创建爬虫项目. scrapy startproject xxx
  2. 进入项目目录. cd xxx
  3. 创建爬虫 scrapy genspider 名称 抓取域
  4. 编写item.py 文件, 定义好数据item
  5. 修改spider中的parse方法. 对返回的响应response对象进行解析. 返回item
  6. 在pipeline中对数据进行保存工作.
  7. 修改settings.py文件, 将pipeline设置为生效, 并设置好优先级
  8. 启动爬虫 scrapy crawl 名称

  1. 引擎(engine)
    scrapy的核心, 所有模块的衔接, 数据流程梳理.
  2. 调度器(scheduler)
    本质上这东西可以看成是一个集合和队列. 里面存放着一堆我们即将要发送的请求. 可以看成是一个url的容器. 它决定了下一步要去爬取哪一个url. 通常我们在这里可以对url进行去重操作.
  3. 下载器(downloader)
    它的本质就是用来发动请求的一个模块. 小白们完全可以把它理解成是一个requests.get()的功能. 只不过这货返回的是一个response对象.
  4. 爬虫(spider)
    这是我们要写的第一个部分的内容, 负责解析下载器返回的response对象.从中提取到我们需要的数据.
  5. 管道(pipeline)
    这是我们要写的第二个部分的内容, 主要负责数据的存储和各种持久化操作.

Scrapy使用

pip install scrapy 建议安装最新版

创建Scrapy项目

scrapy startproject 项目名称

创建爬虫

cd 文件夹  # 进入项目所在文件夹
scrapy genspider 爬虫名称 允许抓取的域名范围
├── mySpider_2
│   ├── __init__.py
│   ├── items.py
│   ├── middlewares.py
│   ├── pipelines.py
│   ├── settings.py
│   └── spiders
│       ├── __init__.py
│       └── youxi.py   # 多了一个这个. 
└── scrapy.cfg

编写Spider

class XiaoyouxiSpider(scrapy.Spider):
    name = 'xiaoyouxi'
    allowed_domains = ['4399.com']  # 当前爬虫允许爬取的域名  白名单
    # 只要不符合以上域名,scrapy自动屏蔽
    start_urls = ['http://www.4399.com/flash/']  # 起始URL

    def parse(self, response):  # 默认的解析位置,主要负责第一个url的解析工作
        li_games = response.xpath("//ul[@class='n-game cf']/li")
        for game in li_games:
            name = game.xpath("./a/b/text()").extract_first()  # 游戏名
            fenlei = game.xpath("./em/a/text()").extract_first()  # 游戏分类
            shijian = game.xpath("./em/text()").extract_first()  # 游戏上线时间
            # print(name, fenlei, shijian)
            """
            使用的是scrapy的xpath,拿到的是selectorlist
            extract_first()提取第一个
            extract()提取全部
            """
            youxi_dict = {
                "name": name,
                "fenlei": fenlei,
                "shijian": shijian
            }
            # 爬虫必须返回请求对象、item(数据,字典充当一条数据)、none(空)
            yield youxi_dict
            # 生成器  可以返回数据  而不打断函数的执行
            # return返回时  函数停止

编写pipelines

存储数据

#管道想要开启,必须在setting中开启
class Youxi4399Pipeline:
    def process_item(self, item, spider):
        print(item)
        with open("data.csv",mode="a",encoding="UTF-8") as f:
            f.write(f"{item['name']},{item['fenlei']},{item['shijian']}\n")
        return item

修改setting

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'  
ROBOTSTXT_OBEY = False  #是否遵守robots协议
LOG_LEVEL ="WARNING"  #增加日志级别,只有警告及以上才会打印在控制台
DOWNLOAD_DELAY = 1  #访问延迟,类似time.sleep(),协程失效
ITEM_PIPELINES = {
   'youxi4399.pipelines.Youxi4399Pipeline': 300,  #300  优先级

数据展示


自定义数据传输结构item

在上述案例中, 我们使用字典作为数据传递的载体, 但是如果数据量非常大. 由于字典的key是随意创建的. 极易出现问题, 此时再用字典就不合适了. Scrapy中提供item作为数据格式的声明位置. 我们可以在items.py文件提前定义好该爬虫在进行数据传输时的数据格式. 然后再写代码的时候就有了数据名称的依据了.

item.py文件

import scrapy

class GameItem(scrapy.Item):
    # 定义数据结构
    name = scrapy.Field()
    category = scrapy.Field()
    date = scrapy.Field()
class Person:
    private String name;
    private int age;
    
 dic = {name: "alex", age: 18}
p = Person( "alex", 18)

spider中可以这样使用

from mySpider_2.items import GameItem

# 以下代码在spider中的parse替换掉原来的字典
item = GameItem()
item["name"] = name
item["category"] = category
item["date"] = date
yield item

快捷执行Scrapy代码

Scrapy目录下新建py文件

from scrapy.cmdline import  execute

if __name__ == '__main__':
    execute("..\\..\\..\\venv\\Scripts\\scrapy.exe crawl xiaoyouxi".split())