• python模块之Scrapy爬虫框架


    一、介绍

    Scrapy 是一个用于爬取网站数据的强大的开源 Python 框架。它提供了一个高级的抓取和数据提取工具集,使您能够快速、灵活地构建和扩展网络爬虫。
    Scrapy 的一些主要优点:

    1. 强大的功能:Scrapy 提供了一套完整的工具和功能,包括请求调度、数据提取、数据存储、数据处理和管道等。它支持异步处理、并发请求、代理、用户代理池、自动限速等功能,使得爬取和处理大规模数据变得更加高效和灵活。
    2. 可扩展性:Scrapy 的架构设计非常灵活,允许您通过编写扩展和中间件来自定义和扩展其功能。您可以根据自己的需求添加新的组件和管道,以满足特定的爬取和数据处理需求。
    3. 分布式支持:Scrapy 支持分布式爬取,可以在多个机器上同时运行爬虫,从而提高爬取速度和效率。它可以与分布式任务队列(如 Redis)和分布式存储系统(如 Elasticsearch)等配合使用,实现高性能的分布式爬取和数据处理。
    4. 文档丰富:Scrapy 提供了详细的官方文档和教程,其中包含了大量的示例代码和使用说明,使得学习和使用 Scrapy 变得更加容易和快速。

    Scrapy 的一些缺点:

    1. 学习曲线较陡:由于 Scrapy 提供了丰富的功能和灵活的架构,对于初学者来说,可能需要一些时间来学习和理解其工作原理和使用方法。
    2. 对于简单任务可能过于复杂:如果您只需要进行简单的网页抓取或数据提取,Scrapy 可能会显得过于复杂和繁重。在这种情况下,使用其他简单的库或工具可能更加合适。
      scrapy官网:https://scrapy.org/
    二、安装
    pip install scrapy
    
    • 1
    三、命令
    1. 创建新的 Scrapy 项目:scrapy startproject
    2. 创建新的爬虫:scrapy genspider
    3. 运行爬虫:scrapy crawl
    4. 列出可用的爬虫:scrapy list
    5. 导出爬取结果:scrapy crawl -o
    6. 运行爬虫并进行调试:scrapy crawl -a -s LOG_LEVEL=DEBUG
    7. 查看爬虫的详细信息:scrapy crawl --spider --nolog -s LOG_LEVEL=INFO
    8. 运行爬虫并限制爬取的页面数量:scrapy crawl -s CLOSESPIDER_ITEMCOUNT=
    9. 使用代理 IP 运行爬虫:scrapy crawl -s HTTP_PROXY=
    10. 运行爬虫并启用自动限速:scrapy crawl -s AUTOTHROTTLE_ENABLED=True
    11. 显示 Scrapy 版本信息:scrapy version
    12. 检查 Scrapy 项目的语法错误:scrapy check
    13. 运行 Scrapy 命令并输出结果到标准输出:scrapy runspider
    14. 检查爬虫文件的语法错误:scrapy check
    15. 生成爬虫的 API 文档:scrapy api [-o ]
    16. 在 Shell 中交互式地调试爬虫:scrapy shell
    17. 导出爬虫的数据到 JSON Lines 格式:scrapy crawl -o .jl
    18. 导出爬虫的数据到 XML 格式:scrapy crawl -o .xml
    19. 运行爬虫并将日志输出到文件:scrapy crawl -s LOG_FILE=
    20. 显示爬虫的统计信息:scrapy stats
    21. 清除爬虫的临时数据:scrapy crawl -s JOBDIR= --nolog
    22. 列出 Scrapy 支持的设置项:scrapy settings --get
    23. 运行爬虫并将结果发送到指定的邮件地址:scrapy crawl --set MAIL_FROM= --set MAIL_TO= --set MAIL_HOST=
    24. 生成爬虫的 Word 文档:scrapy crawl -o .docx --output-format=docx
    25. 运行爬虫并将结果发送到指定的数据库:scrapy crawl -s ITEM_PIPELINES={‘.pipelines.DatabasePipeline’: 300}
    26. 根据爬虫生成可视化的爬取流程图:scrapy graph -o .dot
    27. 将爬虫的数据导入到数据库中:scrapy crawl -o .csv
    28. 检查爬虫的链接和响应情况:scrapy check --spider-cls= --spider-kwargs=‘’
    四、创建项目,文章最后会有该项目具体代码示例
    1. 运行命令创建项目:scrapy startproject scrapySpider
    2. 进入项目目录:cd .\scrapySpider\
    3. 运行命令创建爬虫:scrapy genspider douban movie.douban.com
    4. 目录结构说明
      |-- scrapySpider 项目目录
      
      |   |-- scrapySpider 项目目录
      |   |   |-- spiders 爬虫文件目录
      |   |   |   |-- douban.py 爬虫文件
      
      |   |   |-- items.py 定义数据模型文件,类似于数据库表的模式或数据结构的定义
      |   |   |-- middlewares.py 定义中间件文件,用于对请求和响应进行处理和修改
      |   |   |-- pipelines.py 定义数据处理管道(Pipeline)文件,用于处理爬取到的数据的组件
      |   |   |-- settings.py 定义配置文件,用于配置 Scrapy 项目的各种设置选项和参数
      |   |-- scrapy.cfg 框架中的配置文件,用于指定项目的结构和元数据信息
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    五、douban.py 爬虫文件,继承scrapy.Spider
    1. spider.name:用于指定爬虫的名称。
    2. spider.settings:用于访问爬虫的配置设置。
    3. spider.logger:用于记录日志信息,可参考内置模块logging。
    4. spider.start_urls:包含爬虫的起始 URL 列表。
    5. spider.allowed_domains:包含允许爬虫爬取的域名列表。
    6. spider.crawler:包含当前爬虫的 Crawler 对象。
    7. spider.custom_settings:用于指定自定义的爬虫配置设置。
    8. spider.parse(response: HtmlResponse):用于解析爬取到的响应对象,并提取数据或生成新的请求。
    9. spider.log(message: Any, level: int = logging.DEBUG):用于记录日志信息,可参考内置模块logging。
    10. spider.close(spider: Spider, reason: str):用于关闭爬虫。
    11. spider.from_crawler(crawler: Crawler, *args: Any,):用于从 Crawler 对象创建 Spider 实例。
    12. spider.handles_request(request: Request):用于判断 Spider 是否处理给定的请求。
    13. spider.start_requests():用于生成起始请求对象的迭代器。
    14. spider.update_settings(settings: BaseSettings):用于更新爬虫的配置设置。
    六、settings.py 配置文件

    配置文件文档:https://docs.scrapy.org/en/latest/topics/settings.html

    1. 日志配置
    • LOG_LEVEL:设置日志的级别。可以设置为 DEBUG、INFO、WARNING、ERROR 或 CRITICAL,控制日志输出的详细程度。
    • LOG_ENABLED:设置是否启用日志记录。如果设置为 False,Scrapy 将不会记录任何日志信息。
    • LOG_ENCODING:设置日志文件的编码格式。
    • LOG_FILE:指定日志文件的路径。可以将日志输出到指定的文件中,而不是默认的标准输出。
    • LOG_FILE_APPEND:设置是否以追加模式写入日志文件。如果设置为 True,日志将追加到现有的日志文件中;如果设置为 False,将覆盖现有的日志文件。
    • LOG_FORMAT:设置日志的格式。可以使用预定义的格式字符串,也可以自定义日志格式。
    • LOG_DATEFORMAT:设置日志的日期格式。
    • LOG_FORMATTER:设置日志的格式化器。可以使用预定义的格式化器,也可以自定义格式化器。
    • LOG_LEVEL:设置日志的级别。可以设置为 DEBUG、INFO、WARNING、ERROR 或 CRITICAL,控制日志输出的详细程度。
    • LOG_STDOUT:设置是否将日志输出到标准输出。如果设置为 True,日志将同时输出到日志文件和标准输出。
    • LOG_SHORT_NAMES:设置是否使用短名称作为日志记录器的名称。如果设置为 True,将使用短名称;如果设置为 False,将使用完整的模块名称作为日志记录器的名称。
    • LOGSTATS_INTERVAL:设置记录统计信息的时间间隔,以秒为单位。可以控制统计信息的输出频率
    1. 内存使用和调试的一些配置
    • MEMDEBUG_ENABLED:设置是否启用内存调试功能。如果设置为 True,Scrapy 将会记录和显示内存使用的详细信息,用于调试和分析内存问题。
    • MEMDEBUG_NOTIFY:设置是否在内存使用超过阈值时发送通知。如果设置为 True,当内存使用超过设定的阈值时,Scrapy 将发送通知。
    • MEMUSAGE_ENABLED:设置是否启用内存使用统计功能。如果设置为 True,Scrapy 将会定期记录和显示内存使用情况。
    • MEMUSAGE_LIMIT_MB:设置内存使用的阈值,以兆字节(MB)为单位。当内存使用超过该阈值时,Scrapy 可以采取相应的操作,如发送通知或记录日志。
    • MEMUSAGE_CHECK_INTERVAL_SECONDS:设置内存使用统计的检查间隔,以秒为单位。Scrapy 将每隔指定的时间间隔检查一次内存使用情况。
    • MEMUSAGE_NOTIFY_MAIL:设置接收内存使用通知的电子邮件地址。当启用了内存使用统计功能并且内存使用量超过了设定的阈值时,Scrapy 可以发送邮件通知到指定的邮件地址。
    • MEMUSAGE_WARNING_MB:设置内存使用的警告阈值,以兆字节(MB)为单位。当内存使用超过该阈值时,Scrapy 可以发出警告。
    1. 并发请求相关的配置选项
    • CONCURRENT_ITEMS:用于指定同时处理的 Item 数量。默认情况下,Scrapy 使用值为 100 的并发项数。您可以根据需要调整该值,以控制同时处理的 Item 数量。
    • CONCURRENT_REQUESTS:用于指定同时发出的请求数量。默认情况下,Scrapy 使用值为 16 的并发请求数。您可以根据需要调整该值,以控制同时发出的请求数量。
    • CONCURRENT_REQUESTS_PER_DOMAIN:用于指定每个域名同时发出的请求数量。默认情况下,Scrapy 使用值为 8 的并发请求数。这个选项可以帮助限制对单个域名的并发请求,以避免对目标网站造成过大的负载。
    • CONCURRENT_REQUESTS_PER_IP:用于指定每个 IP 地址同时发出的请求数量。默认情况下,Scrapy 使用值为 0 的并发请求数,表示没有限制。您可以根据需要调整该值,以限制每个 IP 地址的并发请求数量。
    1. AWS(Amazon Web Services)配置选项
    • AWS_ACCESS_KEY_ID:AWS 访问密钥的访问密钥 ID。访问密钥用于身份验证,以便您可以访问 AWS 服务和资源。
    • AWS_SECRET_ACCESS_KEY:AWS 访问密钥的访问密钥密码。访问密钥密码用于身份验证,以便您可以访问 AWS 服务和资源。
    • AWS_SESSION_TOKEN:AWS 会话令牌,用于在使用临时访问凭证时进行身份验证。会话令牌通常与临时访问密钥一起使用。
    • AWS_ENDPOINT_URL:AWS 服务的终端节点 URL。终端节点 URL 指定要访问的 AWS 服务的特定终端节点。根据您的配置和需求,可以使用不同的终端节点 URL。
    • AWS_USE_SSL:设置是否使用 SSL 连接到 AWS 服务。如果设置为 True,Scrapy 将使用 SSL 连接。默认情况下,该选项为 True。
    • AWS_VERIFY:设置是否验证与 AWS 服务建立的 SSL 连接的证书。如果设置为 True,Scrapy 将验证证书。默认情况下,该选项为 True。
    • AWS_REGION_NAME:AWS 区域的名称。AWS 区域是指 AWS 服务的物理位置。根据您的需求,可以指定不同的区域名称。
    1. 默认配置项
    • DEFAULT_ITEM_CLASS:用于指定默认的 Item 类。Item 类是用于定义爬取的数据结构的类。当您创建一个新的 Item 类时,可以将其设置为 DEFAULT_ITEM_CLASS,这样在爬虫中就可以直接使用该类,而无需每次都指定 Item 类。
    • DEFAULT_REQUEST_HEADERS:用于指定默认的请求头。请求头包含了发送给目标网站的 HTTP 请求头信息,如 User-Agent、Accept-Language 等。通过设置 DEFAULT_REQUEST_HEADERS,您可以为每个请求设置默认的请求头,以模拟特定的浏览器或客户端。
    1. 爬取深度和深度优先级相关的配置选项
    • DEPTH_LIMIT:用于限制爬取的深度。默认情况下,它的值为 0,表示没有深度限制。您可以将其设置为正整数,以限制爬取的深度,防止爬虫无限地深入网站。例如,将 DEPTH_LIMIT 设置为 2 将限制爬虫只爬取网页的第一层和第二层链接。
    • DEPTH_PRIORITY:用于控制爬取深度的优先级。默认情况下,Scrapy 使用负数来表示深度优先爬取。较小的负数代表更高的优先级。例如,-1 的优先级高于 -2。您可以根据需要调整 DEPTH_PRIORITY 的值,以改变爬取深度的优先级顺序。
    • DEPTH_STATS_VERBOSE:用于控制深度统计信息的详细程度。默认情况下,它的值为 False,表示只显示每个深度级别的请求数量。如果将其设置为 True,则会显示每个深度级别的请求数量以及每个请求的 URL。这对于调试和分析爬虫的行为非常有用。
    1. DNS 缓存和解析相关的配置选项
    • DNSCACHE_ENABLED:用于控制是否启用 DNS 缓存。默认情况下,它的值为 True,表示启用 DNS 缓存。启用 DNS 缓存可以提高爬虫的性能,因为它会缓存已解析的域名和 IP 地址,避免重复的 DNS 查询。
    • DNSCACHE_SIZE:用于设置 DNS 缓存的大小。它表示可以缓存的域名和 IP 地址的最大数量。默认情况下,它的值为 10000,表示最多可以缓存 10000 个域名和 IP 地址。您可以根据需要调整该值,以适应您的爬虫的规模和需求。
    • DNS_RESOLVER:用于设置自定义的 DNS 解析器。默认情况下,Scrapy 使用系统的默认 DNS 解析器。您可以通过设置 DNS_RESOLVER 为一个自定义的 DNS 解析器对象,来使用自定义的 DNS 解析逻辑。
    • DNS_TIMEOUT:用于设置 DNS 解析的超时时间(以秒为单位)。默认情况下,它的值为 60 秒。如果 DNS 解析超时,Scrapy 将放弃解析该域名并继续处理下一个请求
    1. 下载器(Downloader)和下载相关的配置选项
    • DOWNLOADER:用于设置下载器的类。默认情况下,它的值为 ‘scrapy.core.downloader.Downloader’,表示使用默认的下载器。您可以通过设置 DOWNLOADER 为自定义的下载器类,来替换默认的下载器。
    • DOWNLOADER_HTTPCLIENTFACTORY:用于设置自定义的 HTTP 客户端工厂类。默认情况下,Scrapy 使用 scrapy.core.downloader.webclient.ScrapyHTTPClientFactory 作为 HTTP 客户端工厂类。您可以通过设置 DOWNLOADER_HTTPCLIENTFACTORY 为自定义的工厂类,来使用自定义的 HTTP 客户端。
    • DOWNLOADER_CLIENTCONTEXTFACTORY:用于设置自定义的 SSL 上下文工厂类。默认情况下,Scrapy 使用系统的默认 SSL 上下文工厂类。您可以通过设置 DOWNLOADER_CLIENTCONTEXTFACTORY 为自定义的工厂类,来使用自定义的 SSL 上下文。
    • DOWNLOADER_CLIENT_TLS_CIPHERS:用于设置下载器在进行 TLS(Transport Layer Security)连接时使用的密码套件。默认情况下,它的值为 None,表示使用系统默认的密码套件。
    • DOWNLOADER_CLIENT_TLS_METHOD:用于设置下载器在进行 TLS 连接时使用的加密方法。默认情况下,它的值为 None,表示使用系统默认的加密方法。
    • DOWNLOADER_CLIENT_TLS_VERBOSE_LOGGING:用于控制下载器在进行 TLS 连接时是否启用详细的日志记录。默认情况下,它的值为 False,表示不启用详细日志记录。
    • DOWNLOADER_MIDDLEWARES:用于设置下载器中间件的列表。下载器中间件用于在请求发送到下载器之前或响应返回给引擎之前对请求和响应进行处理。您可以通过设置 DOWNLOADER_MIDDLEWARES 来启用、禁用或调整下载器中间件的顺序。
    • DOWNLOADER_MIDDLEWARES_BASE:下载器中间件的列表。如果您想要在默认中间件的基础上添加自定义中间件,可以使用 DOWNLOADER_MIDDLEWARES_BASE。
    • DOWNLOADER_STATS:用于控制是否启用下载器的统计信息收集。默认情况下,它的值为 True,表示启用统计信息收集。
    • DOWNLOAD_DELAY:用于设置连续请求之间的延迟时间(以秒为单位)。默认情况下,它的值为 0,表示没有延迟。您可以根据需要设置一个正数的值,以避免对服务器造成过大的负载。
    • DOWNLOAD_HANDLERS:用于设置下载处理程序的字典。下载处理程序用于处理不同类型的下载请求,例如 HTTP、HTTPS、FTP 等。您可以根据需要添加或修改下载处理程序。
    • DOWNLOAD_HANDLERS_BASE:下载处理程序的字典。如果您想要在默认处理程序的基础上添加自定义处理程序,可以使用 DOWNLOAD_HANDLERS_BASE。
    • DOWNLOAD_SLOTS:用于设置同时进行下载的最大数量。默认情况下,它的值为 8,表示最多同时进行 8 个下载。您可以根据网络带宽和服务器负载情况,调整该值以控制并发下载的数量。
    • DOWNLOAD_TIMEOUT:用于设置下载超时时间(以秒为单位)。默认情况下,它的值为 180 秒。如果下载超时,Scrapy 将放弃该下载并继续处理下一个请求。
    • DOWNLOAD_MAXSIZE:用于设置下载的最大响应大小(以字节为单位)。默认情况下,它的值为 0,表示没有大小限制。您可以根据需要设置一个正整数的值,以限制下载的响应大小。
    • DOWNLOAD_WARNSIZE:用于设置下载的警告响应大小(以字节为单位)。默认情况下,它的值为 0,表示没有警告大小限制。如果下载的响应大小超过警告大小,Scrapy 将发出警告消息。
    • DOWNLOAD_FAIL_ON_DATALOSS:用于控制是否在下载数据丢失时失败。默认情况下,它的值为 False,表示不在数据丢失时失败。
    1. 去重过滤器(Duplicate Filter)相关的配置选项
    • DUPEFILTER_CLASS:用于设置去重过滤器的类。去重过滤器用于防止重复请求被发送到服务器。默认情况下,Scrapy 使用 scrapy.dupefilters.RFPDupeFilter 作为去重过滤器类。该类使用请求的 URL 哈希值进行去重。您可以通过设置 DUPEFILTER_CLASS 为自定义的去重过滤器类,来实现自定义的去重逻辑。自定义去重过滤器类需要继承自 scrapy.dupefilters.BaseDupeFilter 类,并实现其中的方法。
    • DUPEFILTER_DEBUG:用于控制是否启用去重过滤器的调试模式。默认情况下,它的值为 False,表示不启用调试模式。当启用调试模式时,去重过滤器将记录每个过滤的请求的详细信息,并打印到日志中。
    1. 扩展(Extensions)相关的配置选项
    • EXTENSIONS:用于设置扩展的列表。扩展是 Scrapy 框架中的插件,用于扩展和定制框架的功能。您可以通过设置 EXTENSIONS 来启用或禁用特定的扩展。默认情况下,Scrapy 提供了一些常用的扩展,如日志记录扩展、统计信息扩展等。您也可以编写自己的扩展,并将其添加到 EXTENSIONS 列表中。
    • EXTENSIONS_BASE:默认扩展的列表。如果您想要在默认扩展的基础上添加自定义扩展
    1. 数据存储和访问控制相关的配置选项
    • FEED_TEMPDIR:用于设置临时文件的存储目录路径。在使用 Scrapy 的数据导出功能时,数据会首先被保存到临时文件中,然后再根据配置将其移动到最终的目标位置。FEED_TEMPDIR 用于指定这些临时文件的存储目录。默认情况下,FEED_TEMPDIR 的值为 None,表示使用系统的默认临时目录。您可以通过设置 FEED_TEMPDIR 为自定义的目录路径,来指定临时文件的存储位置。
    • FEED_STORAGE_GCS_ACL:用于设置 Google Cloud Storage (GCS) 上存储的文件的访问控制列表(Access Control List,ACL)。当使用 GCS 存储导出的数据文件时,您可以通过设置 FEED_STORAGE_GCS_ACL 来控制文件的访问权限。“private”: 文件仅限所有者访问、“public-read”: 文件对所有人可读、“bucket-owner-full-control”: 文件对存储桶所有者具有完全控制权限。
    1. FTP(文件传输协议)进行数据传输相关的配置选项
    • FTP_PASSIVE_MODE:用于控制 Scrapy 是否使用被动模式(Passive Mode)进行 FTP 数据传输。被动模式是 FTP 协议中的一种数据传输模式,它允许客户端通过随机的数据端口与服务器进行通信。默认情况下,Scrapy 使用被动模式进行 FTP 数据传输。
    • FTP_PASSWORD:用于设置 FTP 服务器的密码。当 Scrapy 连接到 FTP 服务器时,它将使用指定的密码进行身份验证。您可以将 FTP_PASSWORD 设置为您的 FTP 服务器密码。
    • FTP_USER:用于设置 FTP 服务器的用户名。当 Scrapy 连接到 FTP 服务器时,它将使用指定的用户名进行身份验证。您可以将 FTP_USER 设置为您的 FTP 服务器用户名。
    1. 处理爬取数据的管道(Pipeline)相关的配置选项
    • ITEM_PIPELINES:用于定义启用的管道组件及其顺序。Scrapy 管道是用于处理爬取到的数据的组件,可以对数据进行清洗、验证、存储等操作。通过设置 ITEM_PIPELINES,您可以指定要启用的管道组件及其处理顺序
    • ITEM_PIPELINES_BASE:用于指定 Scrapy 默认的管道组件的基类
    1. 邮箱配置
    • STATSMAILER_RCPTS:接收统计邮件的收件人列表
    • MAIL_FROM:指定发件人的邮件地址
    • MAIL_HOST:SMTP 服务器的主机地址
    • MAIL_PORT:SMTP 服务器的端口号
    • MAIL_USER:登录 SMTP 服务器的用户名
    • MAIL_PASS :登录 SMTP 服务器的密码或授权码
    • MAIL_SSL:指示是否使用 SSL/TLS 连接
    • MAIL_TLS:指示是否启用 TLS连接
    1. 其他配置
    • BOT_NAME:指定爬虫的名称,用于区分不同的爬虫。
    • SPIDER_MODULES:定义包含爬虫代码的 Python 模块的列表。Scrapy 将在这些模块中查找爬虫。
    • NEWSPIDER_MODULE:指定新创建的爬虫的模块名称。当使用 scrapy genspider 命令创建新的爬虫时,将在该模块中生成爬虫代码。
    • USER_AGENT:设置用户代理(User-Agent)头部信息,用于模拟浏览器发送请求。可以设置为浏览器的标识字符串,也可以使用 Scrapy 提供的默认值。
    • URLLENGTH_LIMIT:用于限制爬取的URL长度。当一个URL的长度超过该限制时,Scrapy将会忽略该URL并发出警告。这个选项可以用于控制爬虫爬取的URL长度,以避免爬取过长的URL
    • ROBOTSTXT_OBEY:设置是否遵守 robots.txt 规则。如果设置为 True,Scrapy 将在发送请求之前检查网站的 robots.txt 文件,遵守其中的规则。
    • COOKIES_ENABLED:设置是否启用 Cookie。如果设置为 True,Scrapy 将在请求中发送和接收 Cookie。
    • ASYNCIO_EVENT_LOOP:用于指定使用的异步事件循环。默认情况下,Scrapy 使用 asyncio 作为异步事件循环。您可以根据需要配置其他的异步事件循环,如 Twisted。
    • JOBDIR:JOBDIR 是在 Scrapy 中指定的作业目录路径。作业目录用于存储 Scrapy 作业的状态和临时数据。例如,当您暂停和恢复一个爬虫时,Scrapy 将使用作业目录来保存当前的状态,以便在恢复时能够继续之前的进度。
    • EDITOR:EDITOR 是一个环境变量,用于指定在 Scrapy 中使用的文本编辑器。当您需要编辑 Scrapy 项目中的某些文件时,Scrapy 将会使用指定的编辑器打开这些文件。您可以将其设置为您喜欢的文本编辑器的可执行文件路径。
    • GCS_PROJECT_ID:GCS_PROJECT_ID 是用于 Google Cloud Storage (GCS) 的项目 ID。Google Cloud Storage 是 Google 提供的云存储服务,Scrapy 可以使用 GCS 存储爬取的数据或其他文件。GCS_PROJECT_ID 用于指定要使用的 GCS 项目。
    七、items.py 数据模型的文件,继承scrapy.Item
    1. fields: 用于定义数据项的字段。字段是一个字典,键是字段名,值是字段类型(通常是 scrapy.Field())。
    2. new_attrs: 用于存储动态添加的属性。
    3. new_bases: 用于存储动态添加的基类。
    4. get(key, default=None): 获取指定字段名的字段值。如果字段不存在,则返回默认值。
    5. update(*args, **kwargs): 更新数据项的字段值。可以通过关键字参数或字典来更新字段。
    6. items(): 返回数据项的所有字段名和字段值的键值对。
    7. pop(key, default=None): 移除并返回指定字段名的字段值。如果字段不存在,则返回默认值。
    8. clear(): 清空数据项的所有字段值。
    9. copy(): 返回数据项的浅拷贝副本。
    10. deepcopy(memo=None): 返回数据项的深拷贝副本。
    11. keys(): 返回数据项的所有字段名。
    12. popitem(): 移除并返回数据项中的任意字段名和字段值的键值对。
    13. setdefault(key, default=None): 获取指定字段名的字段值。如果字段不存在,则设置默认值并返回。
    14. values(): 返回数据项的所有字段值
    八、pipelines.py 数据处理管道的文件

    需要在settings.py中开启管道:ITEM_PIPELINES

    1. open_spider(spider): 当爬虫启动时调用的方法。可以在此方法中进行初始化操作,例如打开文件或连接数据库。
    2. close_spider(spider): 当爬虫关闭时调用的方法。可以在此方法中进行清理操作,例如关闭文件或断开数据库连接。
    3. process_item(item, spider): 对每个爬取到的数据项进行处理的方法。可以在此方法中实现数据的清洗、转换或其他自定义操作。
    4. from_crawler(crawler): 用于从爬虫配置中获取全局设置。可以在此方法中获取配置信息,例如数据库连接参数或其他全局设置。
    九、middlewares.py 中间件文件
    1. SpiderMiddleware:下载中间件,下载中间件是在请求发送到下载器之前或响应从下载器返回到引擎之前进行处理的组件。它们可以用于修改请求、处理响应、设置代理、处理异常等操作,需要在settings.py中开启请求中间件:SPIDER_MIDDLEWARES
    • process_spider_input(response, spider):在引擎将响应发送给爬虫之前被调用,可以修改响应或进行预处理
    • process_spider_output(response, result, spider):在爬虫返回的结果被引擎处理之前被调用,可以修改结果或进行后处理
    • process_spider_exception(response, exception, spider):在爬虫过程中发生异常时被调用,可以处理异常并返回新的结果或请求
    • process_start_requests(self, start_requests, spider):在爬虫启动时,该方法用于处理初始请求
    1. DownloaderMiddleware:爬虫中间件,在引擎将响应发送给爬虫之前或将请求发送给下载器之前进行处理的组件。它们可以用于修改请求、处理响应、处理异常等操作,需要在settings.py中响应中间件:DOWNLOADER_MIDDLEWARES
    • process_request(request, spider):在请求发送到下载器之前被调用,可以修改请求或进行预处理。返回None则继续进行请求、返回resposne则不再继续请求将结果直接返回给引擎、如果对request进行修改,并返回request对象,则将请求提高给调度器重新请求
    • process_response(request, response, spider):在响应从下载器返回到引擎之前被调用,可以修改响应或进行后处理。返会response则将响应结果直接返回给引擎、返回request则将请求交给引擎,引擎交给调度器,调度器重新
    • process_exception(request, exception, spider):在下载过程中发生异常时被调用,可以处理异常并返回新的请求或响应。
      九、scrapy.cmdline 模块
      1.execute(argv=None, settings=None):执行命令行命令。可以通过传递不同的参数来执行不同的操作,如运行爬虫、创建项目等。argv 参数是一个列表,用于指定命令行参数。settings 参数是一个 Settings 对象,用于指定 Scrapy 项目的配置信息。
    from scrapy import cmdline
    
    cmdline.execute('scrapy crawl douban'.split())
    
    • 1
    • 2
    • 3
    十、scrapy.http:处理 HTTP 请求和响应的类和工具
    1. from scrapy.http import Response:用于表示一个 HTTP 响应。包含响应的状态码、响应头、响应体等信息
    • Response(url,status,headers,body,flags,request,certificate,ip_address,protocol):创建Response对象
    • url (str): 响应的 URL 地址。
    • status (int): 响应的状态码。
    • headers (dict or Headers): 响应的头部信息。可以是字典形式的头部信息,也可以是 Headers 对象。
    • body (bytes or str): 响应的主体内容。可以是字节串或字符串形式的内容。flags (str): 响应的标志位。这是一个可选参数,用于表示响应的一些特殊标志。
    • request (Request): 生成该响应的请求对象。
    • certificate (dict): 响应的证书信息。这是一个可选参数,用于表示响应使用的证书。
    • ip_address (str): 响应的 IP 地址。这是一个可选参数,用于表示响应的 IP 地址。
    • protocol (str): 响应的协议。这是一个可选参数,用于表示响应使用的协议
    • response.xpath(query, namespaces=None, **kwargs):使用 XPath 表达式从响应中提取数据。返回一个列表或单个结果
    • query 是 XPath 表达式,
    • namespaces 是命名空间字典,
    • kwargs 是额外的命名参数。
    • response.css(query, **kwargs):使用 CSS 选择器从响应中提取数据。返回一个列表或单个结果
    • query 是 CSS 选择器表达式,
    • kwargs 是额外的命名参数。
    • response.follow(url, callback=None, method=‘GET’, headers=None, body=None, cookies=None, meta=None, encoding=‘utf-8’):跟进单个链接,根据提取的链接继续跟进请求。返回一个新的请求对象
    • url 是要跟进的链接,
    • callback 是回调函数,
    • method 是请求方法,
    • headers 是请求头部信息,
    • body 是请求体内容,
    • cookies 是请求的 Cookie,
    • meta 是请求的元数据,
    • encoding 是请求的编码方式。
    • response.follow_all(urls, callback,method,headers, body,cookies,meta,encoding,priority,dont_filter,errback,cb_kwargs,flags,css, xpath):跟进多个链接,根据提取的链接继续跟进请求。
    • urls:一个 URL 列表,表示要跟进的多个链接。
    • callback:可选参数,指定用于处理跟进链接的回调函数。
    • method:可选参数,指定请求方法(GET、POST 等)。
    • headers:可选参数,指定请求头。
    • body:可选参数,指定请求体。
    • cookies:可选参数,指定请求的 cookies。
    • meta:可选参数,指定要传递给跟进请求的元数据。encoding:可选参数,指定响应的编码方式。
    • priority:可选参数,指定请求的优先级。
    • dont_filter:可选参数,指定是否对跟进请求进行去重过滤。
    • errback:可选参数,指定处理请求错误的回调函数。
    • cb_kwargs:可选参数,指定传递给回调函数的关键字参数。
    • flags:可选参数,指定请求的标志。
    • css:可选参数,指定使用 CSS 选择器提取链接。
    • xpath:可选参数,指定使用 XPath 提取链接。
    • response.replace(body=None, url=None, headers=None, encoding=‘utf-8’):创建一个新的 HtmlResponse 对象,替换部分或全部属性。返回一个新的响应对象
    • body 是新的响应内容,
    • url 是新的 URL 地址,
    • headers 是新的头部信息,
    • encoding 是新的编码方式。
    • response.urljoin(url):用来构造url
    • response.copy():创建当前响应的副本。
    • response.url:响应的 URL 地址。
    • response.status:响应的状态码。
    • response.headers:响应的头部信息。
    • response.body:响应的原始 HTML 内容。
    • response.request:生成该响应的请求对象。
    • response.text:返回响应的文本内容。
    • response.cb_kwargs:一个字典,包含在请求中传递给回调函数的关键字参数(callback arguments)。
    • response.certificate:一个表示响应的SSL证书的对象。您可以使用该属性获取有关证书的信息,如证书的颁发机构、过期日期等。
    • response.ip_address:响应的IP地址,即响应所在服务器的IP地址。
    • response.flags:一个整数,表示响应的一些标志(flags)。这些标志可以提供关于响应的额外信息,如是否是重定向、是否是代理响应等。
    • response.meta:一个字典,包含与响应相关的元数据。您可以使用该属性来传递额外的信息给后续的处理器,如中间件、回调函数等。
    • response.protocol:响应的协议类型,如HTTP、HTTPS等。
    1. from scrapy.http import TextResponse:继承自 Response,用于表示文本类型的 HTTP 响应。提供了更方便的文本处理方法。
    • response.json():将响应的内容解析为 JSON 格式
    • response.encoding:响应的编码方式。
    • response.selector:返回一个 Selector 对象,用于进一步处理和解析响应内容
    1. from scrapy.http import HtmlResponse:继承自 TextResponse,用于表示 HTML 类型的 HTTP 响应的类
    • HtmlResponse(url,status,headers,body,flags,request,certificate,ip_address,protoco):创建 HtmlResponse 对象
    • url (str): 响应的 URL 地址。
    • status (int): 响应的状态码。
    • headers (dict or Headers): 响应的头部信息。可以是字典形式的头部信息,也可以是 Headers 对象。
    • body (bytes or str): 响应的主体内容。可以是字节串或字符串形式的内容。flags (str): 响应的标志位。这是一个可选参数,用于表示响应的一些特殊标志。
    • request (Request): 生成该响应的请求对象。
    • certificate (dict): 响应的证书信息。这是一个可选参数,用于表示响应使用的证书。
    • ip_address (str): 响应的 IP 地址。这是一个可选参数,用于表示响应的 IP 地址。
    • protocol (str): 响应的协议。这是一个可选参数,用于表示响应使用的协议
    1. from scrapy.http import XmlResponse:继承自 TextResponse,用于表示 XML 类型的 HTTP 响应。提供了解析 XML 数据的方法。
    2. from scrapy.http import Request:用于表示一个 HTTP 请求。可以设置请求的 URL、请求方法、请求头、请求体等信息
    • Request(url,callback,method,headers,body,cookies,meta,encoding,priority,dont_filteerrback,flags,cb_kwargs):创建 Request 对象
    • url:请求的 URL 地址。callback:请求完成后,响应返回时要调用的回调函数。method:请求的 HTTP 方法,例如 GET、POST 等。
    • headers:请求的头部信息,包含了一些请求的元数据,如 User-Agent、Referer 等。
    • body:请求的主体内容,通常在 POST 请求中使用。
    • cookies:请求的 Cookies,可以是字典形式的 Cookies 数据。
    • meta:一个字典对象,用于在请求之间传递数据。可以在不同的请求之间共享数据。
    • encoding:请求的编码方式,用于处理响应内容的编码。
    • priority:请求的优先级,用于调整请求的顺序。默认为 0,数值越小,优先级越高。
    • dont_filter:布尔值,表示是否对该请求进行去重过滤。默认情况下,Scrapy 会对相同的请求进行去重,如果设置为 True,则禁用去重过滤。
    • flags:一个标志位,用于标识请求的特殊属性或状态。
    • request.url:请求的 URL 地址。
    • request.flags:一个标志位,用于标识请求的特殊属性或状态。
    • request.attributes:一个字典对象,用于存储请求的自定义属性。
    • request.method:请求的 HTTP 方法,例如 GET、POST 等。
    • request.meta:一个字典对象,用于在请求之间传递数据。可以在不同的请求之间共享数据。
      request.meta['proxy'] #指定请求使用的代理服务器
      request.meta['headers'] #设置请求的头部信息
      request.meta['dont_redirect'] #控制请求是否自动重定向
      request.meta['dont_retry'] #控制请求是否自动重试
      request.meta['handle_httpstatus_list'] #设置要处理的HTTP状态码列表
      request.meta['cookiejar'] #指定请求使用的cookiejar
      request.meta['download_timeout'] #设置请求的下载超时时间
      request.meta['download_slot'] #指定请求使用的下载槽(slot)
      request.meta['download_latency'] #指定请求的下载延迟时间
      request.meta['priority'] #设置请求的优先级。
      request.meta['dont_cache'] #控制请求是否被缓存。
      request.meta['retry_times'] #设置请求的重试次数。
      request.meta['redirect_urls'] #存储请求的重定向URL列表。
      request.meta['redirect_reasons'] #存储请求的重定向原因列表。
      request.meta['redirected'] #标记请求是否已经被重定向。
      request.meta['handle_httpstatus_all'] #设置是否处理所有的HTTP状态码。
      request.meta['handle_httpstatus_ignore'] #设置要忽略的HTTP状态码列表。
      request.meta['handle_httpstatus_exists'] #设置要处理的存在的HTTP状态码列表。
      request.meta['handle_httpstatus_nonexistent'] #设置要处理的不存在的HTTP状态码列表。
      request.meta['retry_http_codes'] #设置触发请求重试的HTTP状态码列表。
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
    • request.cb_kwargs:一个字典对象,用于将参数传递给回调函数。
    • request.cookies:请求的 Cookies,可以是字典形式的 Cookies 数据。
    • request.headers:请求的头部信息,包含了一些请求的元数据,如 User-Agent、Referer 等。
    • request.body:请求的主体内容,通常在 POST 请求中使用。
    • request.callback:请求完成后,响应返回时要调用的回调函数。
    • request.dont_filter:布尔值,表示是否对该请求进行去重过滤。默认情况下,Scrapy 会对相同的请求进行去重,如果设置为 True,则禁用去重过滤。
    • request.encoding:请求的编码方式,用于处理响应内容的编码。
    • request.errback:请求完成后,如果发生错误,要调用的回调函数。
    • request.priority:请求的优先级,用于调整请求的顺序。默认为 0,数值越小,优先级越高。
    1. from scrapy.http import JsonRequest:继承自 Request,用于发送 JSON 格式的 HTTP 请求。
    • JsonRequest(url,callback,method,headers,body,cookies,meta,encoding,priority,dont_filteerrback,flags,cb_kwargs,dumps_kwargs):创建 Request 对象
    • url:请求的 URL 地址。callback:请求完成后,响应返回时要调用的回调函数。method:请求的 HTTP 方法,例如 GET、POST 等。
    • headers:请求的头部信息,包含了一些请求的元数据,如 User-Agent、Referer 等。
    • body:请求的主体内容,通常在 POST 请求中使用。
    • cookies:请求的 Cookies,可以是字典形式的 Cookies 数据。
    • meta:一个字典对象,用于在请求之间传递数据。可以在不同的请求之间共享数据。
    • encoding:请求的编码方式,用于处理响应内容的编码。
    • priority:请求的优先级,用于调整请求的顺序。默认为 0,数值越小,优先级越高。
    • dont_filter:布尔值,表示是否对该请求进行去重过滤。默认情况下,Scrapy 会对相同的请求进行去重,如果设置为 True,则禁用去重过滤。
    • flags:一个标志位,用于标识请求的特殊属性或状态。
    • dumps_kwargs:用于序列化请求体数据的关键字参数
    1. from scrapy.http import FormRequest:继承自 Request,用于发送表单类型的 HTTP 请求。可以方便地设置表单字段和文件上传
    • FormRequest(url,callback,method,headers,body,cookies,meta,encoding,priority,dont_filteerrback,flags,cb_kwargs,formdata):创建 Request 对象
    • url:请求的 URL 地址。callback:请求完成后,响应返回时要调用的回调函数。method:请求的 HTTP 方法,例如 GET、POST 等。
    • headers:请求的头部信息,包含了一些请求的元数据,如 User-Agent、Referer 等。
    • body:请求的主体内容,通常在 POST 请求中使用。
    • cookies:请求的 Cookies,可以是字典形式的 Cookies 数据。
    • meta:一个字典对象,用于在请求之间传递数据。可以在不同的请求之间共享数据。
    • encoding:请求的编码方式,用于处理响应内容的编码。
    • priority:请求的优先级,用于调整请求的顺序。默认为 0,数值越小,优先级越高。
    • dont_filter:布尔值,表示是否对该请求进行去重过滤。默认情况下,Scrapy 会对相同的请求进行去重,如果设置为 True,则禁用去重过滤。
    • flags:一个标志位,用于标识请求的特殊属性或状态。
    • formdata:表单数据,可以是字典或可迭代对象。
    1. from scrapy.http import XmlRpcRequest:继承自 Request,用于发送 XML-RPC 格式的 HTTP 请求。
    2. from scrapy.http import Headers:用于表示 HTTP 请求或响应的头部信息。可以添加、获取、删除头部字段。
    十一、scrapy.selector:选择和提取网页数据的类和工具
    1. Selector对象:from scrapy.selector import Selector
    • Selector(response,text,type,root):创建 Selector 对象
    • selector.response:获取与 Selector 对象关联的响应对象。可以通过 selector.response 访问关联的响应对象。
    • selector.xpath(expression, namespaces=None):使用 XPath 表达式从文档中选择元素。返回一个新的 Selector 对象,可以继续对其进行进一步的选择或提取操作。示例使用:selector.xpath(‘xpath_expression’)。
    • selector.css(query):使用 CSS 选择器从文档中选择元素。返回一个新的 Selector 对象,可以继续对其进行进一步的选择或提取操作。示例使用:selector.css(‘selector’)。
    • selector.get():返回选择器匹配的第一个元素。如果没有匹配的元素,则返回 None。示例使用:selector.get()。
    • selector.getall():返回选择器匹配的所有元素组成的列表。如果没有匹配的元素,则返回空列表。示例使用:selector.getall()。
    • selector.remove():从文档中删除选择器匹配的元素。该方法会修改原始的 Selector 对象。
    • selector.drop():从文档中删除选择器匹配的元素,并返回一个新的 Selector 对象,该对象不包含被删除的元素。
    • selector.extract():将选择器对象转换为字符串。可以获取选择器对象表示的 HTML 或 XML 内容。示例使用:selector.extract()。
    • selector.extract_first():用于提取选择器匹配的第一个元素的文本内容
    • selector.re_first(regex_pattern):使用正则表达式从选择器对象的文本内容中提取第一个匹配项。示例使用:selector.re_first(‘regex_pattern’)。
    • selector.mro():返回 Selector 类的方法解析顺序(Method Resolution Order)列表。可以用于查看方法的继承关系。
    • selector.register_namespace(prefix, uri):注册 XML 命名空间前缀和 URI。在使用 XPath 表达式时,如果文档中包含命名空间,则需要先注册命名空间。
    • selector.remove_namespaces():从选择器对象及其子节点中移除所有命名空间。可以在处理带命名空间的 XML 文档时使用该方法
    1. SelectorList对象:from scrapy.selector import SelectorList
    十二、signals:用于处理信号的模块,from scrapy import signals
    1. signals.spider_opened:当爬虫开始运行时触发的信号。
    2. signals.item_error:当处理爬取项(item)时发生错误时触发的信号。
    3. signals.item_passed:当爬取项(item)成功通过所有的处理管道(pipeline)时触发的信号。
    4. signals.item_dropped:当爬取项(item)被丢弃时触发的信号。
    5. signals.item_scraped:当爬虫成功解析出一个爬取项(item)时触发的信号。
    6. signals.bytes_received:当接收到字节数据时触发的信号。
    7. signals.engine_started:当引擎开始运行时触发的信号。
    8. signals.engine_stopped:当引擎停止运行时触发的信号。
    9. signals.feed_exporter_closed:当Feed输出器关闭时触发的信号。
    10. signals.headers_received:当接收到HTTP响应头部时触发的信号。
    11. signals.request_dropped:当请求被丢弃时触发的信号。
    12. signals.request_left_downloader:当请求离开下载器时触发的信号。
    13. signals.request_reached_downloader:当请求到达下载器时触发的信号。
    14. signals.request_received:当接收到请求时触发的信号。
    15. signals.request_scheduled:当请求被调度时触发的信号。
    16. signals.response_downloaded:当下载器成功下载响应时触发的信号。
    17. signals.spider_closed:当爬虫关闭时触发的信号。
    18. signals.spider_error:当爬虫发生错误时触发的信号。
    19. signals.response_received:当接收到响应时触发的信号。
    20. signals.spider_idle:当爬虫处于空闲状态时触发的信号。
    21. signals.stats_spider_closed:当爬虫统计信息关闭时触发的信号。
    22. signals.stats_spider_closing:当爬虫统计信息即将关闭时触发的信号。
    23. signals.stats_spider_opened:当爬虫统计信息打开时触发的信号。
    十三、scrapy.mail:邮箱模块
    1. mailSender = scrapy.mail.MailSender(smtphost,mailfrom,smtpuser,smtppass,smtppor,smtptls,smtpssl,debug):创建发送邮件对象
    • smtphost:SMTP 服务器的主机名。
    • mailfrom:发件人的邮件地址。
    • smtpuser:用于登录 SMTP 服务器的用户名。
    • smtppass:用于登录 SMTP 服务器的密码。
    • smtpport:SMTP 服务器的端口号。
    • smtptls:一个布尔值,指示是否使用 TLS 加密传输。
    • smtpssl:一个布尔值,指示是否使用 SSL 加密传输。
    • debug:一个布尔值,指示是否启用调试模式。
    1. mailSender = scrapy.maile.MailSender.from_settings(settings):从项目的设置中创建一个邮件发送器(MailSender)实例
    2. mailSender.send(to,subject,body, cc, attachs,mimetype, charset,_callback)
    • to:接收邮件的邮件地址,可以是一个字符串或一个邮件地址列表,用于指定多个收件人。
    • subject:邮件的主题,通常是一个字符串。
    • body:邮件的正文内容,可以是纯文本或者包含 HTML 标签的富文本。
    • cc:抄送给其他收件人的邮件地址,可以是一个字符串或一个邮件地址列表。
    • attachs:附件文件的路径,可以是一个字符串或一个包含多个附件路径的列表。
    • mimetype:正文的 MIME 类型,默认为 “text/plain”,可以根据需要设置为其他类型,如 “text/html”。
    • charset:字符集,可以是一个字符串。
    • _callback:一个可选的回调函数,用于在邮件发送完成后执行特定的操作。
    十四、事件监控配置

    1.事件监控官网:https://scrapeops.io/app/jobs

    • 安装:pip install scrapeops-scrapy
    • 配置:settings.py
      ## settings.py
      
      ## 你的平台秘钥
      SCRAPEOPS_API_KEY = 'YOUR_API_KEY'
      
      ## 添加ScrapeOps扩展
      EXTENSIONS = {
          'scrapeops_scrapy.extension.ScrapeOpsMonitor': 500, 
      }
      
      ## 更新下载器中间件
      DOWNLOADER_MIDDLEWARES = { 
          'scrapeops_scrapy.middleware.retry.RetryMiddleware': 550, 
      
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
    1. scrapy发送邮箱提醒,使用
    • 配置settings.py
      EXTENSIONS = {
           'scrapy.extensions.statsmailer.StatsMailer': 500,
      }
      STATSMAILER_RCPTS = ['你的邮箱']
      MAIL_FROM = '你的邮箱'
      MAIL_HOST = 'smtp.qq.com'
      MAIL_PORT = 465
      MAIL_USER = '你的邮箱'
      #配置好smtp服务给的密码
      MAIL_PASS = ''
      MAIL_SSL=True
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    • 修改爬虫文件
      import scrapy
      import scrapy.cmdline
      from scrapy.mail import MailSender
      
      
      class SeleniumTxWorkSpider(scrapy.Spider):
          ....
      
          def close(self, spider, reason):
              mail_sender = MailSender.from_settings(spider.settings)
              print(type(spider.settings))
              return mail_sender.send(to=spider.settings['STATSMAILER_RCPTS'],subject='python', body='爬虫结束')
              
      if __name__ == '__main__':
          scrapy.cmdline.execute('scrapy crawl seleniumTxWork'.split())
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
    十五、爬取豆瓣案例,通过中间件使用代理,需安装scrapy、pymysql、pymongo、fake_useragent、requests
    1. 运行命令创建项目:scrapy startproject scrapySpider
    2. 进入项目目录:cd .\scrapySpider\
    3. 运行命令创建爬虫:scrapy genspider douban movie.douban.com
    4. 目录结构说明
      |-- scrapySpider 项目目录
      
      |   |-- scrapySpider 项目目录
      |   |   |-- spiders 爬虫文件目录
      |   |   |   |-- douban.py 爬虫文件
      
      |   |   |-- items.py 定义数据模型文件,类似于数据库表的模式或数据结构的定义
      |   |   |-- middlewares.py 定义中间件文件,用于对请求和响应进行处理和修改
      |   |   |-- pipelines.py 定义数据处理管道(Pipeline)文件,用于处理爬取到的数据的组件
      |   |   |-- settings.py 定义配置文件,用于配置 Scrapy 项目的各种设置选项和参数
      |   |-- scrapy.cfg 框架中的配置文件,用于指定项目的结构和元数据信息
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
    5. 创建快代理文件scrapySpider>kuaidaili.py:https://www.kuaidaili.com/
      import requests
      
      
      class Kuaidaili():
          request_url = {
              # 获取代理ip前面
              'getIpSignature': 'https://auth.kdlapi.com/api/get_secret_token',
              # 获取代理ip
              'getIp': 'https://dps.kdlapi.com/api/getdps?secret_id=oy2q5xu76k4s8olx59et&num=1&signature={}'
          }
      
          headers = {
              'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
          }
      
          ip_use = '购买代理用户名'
          ip_password = '购买代理密码'
      
          def __init__(self):
              '''创建request会话对象'''
              self.request_session = requests.Session()
              self.request_session.headers.update(self.headers)
      
          # 获取代理ip签名
          @classmethod
          def get_ip_url(cls):
              par = {
                  'secret_id': 'oy2q5xu76k4s8olx59et',
                  'secret_key': '5xg6gvouc0vszfw0kxs1a8vrw1r6ity7'
              }
              response = requests.post(cls.request_url['getIpSignature'],data=par)
              response_data = response.json()
              return cls.request_url['getIp'].format(response_data['data']['secret_token'])
      
          @classmethod
          def get_ip(cls):
              url = cls.get_ip_url()
              response = requests.get(url)
              return f'http://{cls.ip_use}:{cls.ip_password}@{response.text}/'
      
      if __name__ == '__main__':
          kuaidaili = Kuaidaili()
          print(kuaidaili.get_ip())
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43

    6 .爬取豆瓣案例

    • douban.py
      import scrapy
      from scrapy import cmdline
      from scrapy.http import HtmlResponse,Request
      from scrapySpider.items import DoubanItem
      
      class DoubanSpider(scrapy.Spider):
          name = 'douban'
          allowed_domains = ['movie.douban.com']
          start_urls = ['https://movie.douban.com/top250']
      
          def parse(self, response: HtmlResponse,**kwargs):
              video_list = response.xpath('//ol[@class="grid_view"]/li')
              for li in video_list:
                  item = DoubanItem()
                  item['title'] = li.xpath('.//div[@class="hd"]/a/span[1]/text()').extract_first()
                  item['rating'] = li.xpath('.//div[@class="bd"]//span[@class="rating_num"]/text()').extract_first()
                  item['quote'] = li.xpath('.//div[@class="bd"]//p[@class="quote"]/span/text()').extract_first()
                  detail_url = li.xpath('.//div[@class="hd"]/a/@href').extract_first()
                  yield Request(url=detail_url,callback=self.get_detail_info,meta={'item':item})
              #获取下一页数据
              next_page_url = response.xpath('//div[@class="paginator"]//link[@rel="next"]/@href').extract_first()
              if next_page_url:
                  yield Request(url=response.urljoin(next_page_url),callback=self.parse)
      
          #重写start_requests获取多页数据
          # def start_requests(self):
          #     for i in range(0,2):
          #         yield Request(url=f'{self.start_urls[0]}?start={i*25}&filter=',dont_filter=True,callback=self.parse)
      
          def get_detail_info(self,response:HtmlResponse):
              item = response.meta['item']
              detail = response.xpath('//span[@class="all hidden"]/text()').extract_first()
              if not detail:
                  detail = response.xpath('//div[@id="link-report-intra"]/span[1]/text()').extract_first()
              item['intro'] = detail.strip()
              return item
      
      if __name__ == '__main__':
          cmdline.execute('scrapy crawl douban'.split())
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
    • settings.py
      # Scrapy settings for scrapySpider project
      #
      # For simplicity, this file contains only settings considered important or
      # commonly used. You can find more settings consulting the documentation:
      #
      #     https://docs.scrapy.org/en/latest/topics/settings.html
      #     https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
      #     https://docs.scrapy.org/en/latest/topics/spider-middleware.html
      
      BOT_NAME = "scrapySpider"
      
      SPIDER_MODULES = ["scrapySpider.spiders"]
      NEWSPIDER_MODULE = "scrapySpider.spiders"
      
      
      # Crawl responsibly by identifying yourself (and your website) on the user-agent
      # USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36"
      
      # Obey robots.txt rules
      ROBOTSTXT_OBEY = False
      
      # Configure maximum concurrent requests performed by Scrapy (default: 16)
      #CONCURRENT_REQUESTS = 32
      
      # Configure a delay for requests for the same website (default: 0)
      # See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
      # See also autothrottle settings and docs
      #DOWNLOAD_DELAY = 3
      # The download delay setting will honor only one of:
      #CONCURRENT_REQUESTS_PER_DOMAIN = 16
      #CONCURRENT_REQUESTS_PER_IP = 16
      
      # Disable cookies (enabled by default)
      #COOKIES_ENABLED = False
      
      # Disable Telnet Console (enabled by default)
      #TELNETCONSOLE_ENABLED = False
      
      # Override the default request headers:
      DEFAULT_REQUEST_HEADERS = {
         "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
         "Accept-Language": "en",
      }
      
      # Enable or disable spider middlewares
      # See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
      #SPIDER_MIDDLEWARES = {
      #    "scrapySpider.middlewares.ScrapyspiderSpiderMiddleware": 543,
      #}
      
      # Enable or disable downloader middlewares
      # See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
      DOWNLOADER_MIDDLEWARES = {
         "scrapySpider.middlewares.DoubanDownloaderMiddleware": 543,
      }
      
      # Enable or disable extensions
      # See https://docs.scrapy.org/en/latest/topics/extensions.html
      # EXTENSIONS = {
      #    'scrapeops_scrapy.extension.ScrapeOpsMonitor': 500,
      # }
      
      # Configure item pipelines
      # See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
      ITEM_PIPELINES = {
         "scrapySpider.pipelines.MysqlPipeLine": 300,
         "scrapySpider.pipelines.MongoPipeLine": 301,
      }
      
      # Enable and configure the AutoThrottle extension (disabled by default)
      # See https://docs.scrapy.org/en/latest/topics/autothrottle.html
      #AUTOTHROTTLE_ENABLED = True
      # The initial download delay
      #AUTOTHROTTLE_START_DELAY = 5
      # The maximum download delay to be set in case of high latencies
      #AUTOTHROTTLE_MAX_DELAY = 60
      # The average number of requests Scrapy should be sending in parallel to
      # each remote server
      #AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
      # Enable showing throttling stats for every response received:
      #AUTOTHROTTLE_DEBUG = False
      
      # Enable and configure HTTP caching (disabled by default)
      # See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
      #HTTPCACHE_ENABLED = True
      #HTTPCACHE_EXPIRATION_SECS = 0
      #HTTPCACHE_DIR = "httpcache"
      #HTTPCACHE_IGNORE_HTTP_CODES = []
      #HTTPCACHE_STORAGE = "scrapy.extensions.httpcache.FilesystemCacheStorage"
      
      # Set settings whose default value is deprecated to a future-proof value
      REQUEST_FINGERPRINTER_IMPLEMENTATION = "2.7"
      TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
      FEED_EXPORT_ENCODING = "utf-8"
      
      #日志配置
      # LOG_FILE = 'log.log'
      # LOG_FILE_APPEND = False
      # LOG_LEVEL = 'INFO'
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 93
      • 94
      • 95
      • 96
      • 97
      • 98
      • 99
      • 100
    • 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 DoubanItem(scrapy.Item):
          # define the fields for your item here like:
          # name = scrapy.Field()
          title = scrapy.Field()
          rating = scrapy.Field()
          quote = scrapy.Field()
          intro = scrapy.Field()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
    • 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
      import pymongo
      
      video_spider = ['douban']
      
      class DoubanPipeline:
          def process_item(self, item, spider):
              print(item)
              return item
      
      
      class MysqlPipeLine:
      
          def open_spider(self, spider):
              self.spider = spider
              self.mysql = pymysql.connect(host='localhost',port=3306,user='root',password='root')
              self.cursor = self.mysql.cursor()
              # 创建video数据库和相关爬虫表
              if self.spider.name in video_spider:
                  self.create_db('video')
      
          '''创建数据库'''
          def create_db(self,db_name):
               sql = f'''CREATE DATABASE IF NOT EXISTS {db_name}'''
               try:
                   self.cursor.execute(sql)
                   self.mysql.select_db(db_name)
                   if self.spider.name == 'douban':
                       self.create_douban_table()
               except Exception as e:
                  print(f'创建{db_name}数据库失败:{e}')
      
          '''创建表douban'''
          def create_douban_table(self):
              sql = f'''
              CREATE TABLE IF NOT EXISTS {self.spider.name}(
              id INT AUTO_INCREMENT,
              title VARCHAR(255),
              rating FLOAT,
              quote VARCHAR(255),
              intro TEXT,
              PRIMARY KEY(id)
              )
              '''
              try:
                  self.cursor.execute(sql)
              except Exception as e:
                  print(f'创建douban表失败:{e}')
      
          def process_item(self, item, spider):
              if spider.name == 'douban':
                  sql = f'''INSERT INTO {spider.name}(title,rating,quote,intro) VALUES(%(title)s,%(rating)s,%(quote)s,%(intro)s)'''
                  try:
                      item['rating'] = float(item['rating'])
                      self.cursor.execute(sql,dict(item))
                      self.mysql.commit()
                  except Exception as e:
                      print(f'”{item["title"]}”插入失败:{e}')
                      self.mysql.rollback()
              return item
      
          def close_spider(self,spider):
              self.mysql.close()
      
      
      class MongoPipeLine:
      
          def open_spider(self, spider):
              self.spider = spider
              self.mongo = pymongo.MongoClient(host='localhost',port=27017)
              # 创建video数据库和相关爬虫表
              if self.spider.name in video_spider:
                  self.cursor = self.mongo['video'][self.spider.name]
      
          def process_item(self, item, spider):
              try:
                  self.cursor.insert_one(dict(item))
              except Exception as e:
                  print(f'”{item["title"]}”插入失败:{e}')
      
              return item
      
          def close_spider(self, spider):
              self.mongo.close()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
    • 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
      from fake_useragent import UserAgent
      from scrapy.http import Request,HtmlResponse
      from scrapySpider.kuaidaili import Kuaidaili
      
      # useful for handling different item types with a single interface
      from itemadapter import is_item, ItemAdapter
      
      class DoubanDownloaderMiddleware:
      
          def __init__(self):
              self.ua = UserAgent()
              self.kuaidaili = Kuaidaili()
              #初始化一个代理ip
              self.first_ip = self.kuaidaili.get_ip()
      
          @classmethod
          def from_crawler(cls, crawler):
              s = cls()
              crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
              return s
      
          def process_request(self, request:Request, spider):
              #设置UA
              request.headers['User-Agent'] = self.ua.random
              #设置代理
              request.meta['proxy'] = self.first_ip
              request.meta['download_timeout'] = 5
              spider.logger.info(f'ip:{request.meta["proxy"]}')
              return None
      
          def process_response(self, request, response:HtmlResponse, spider):
              spider.logger.info(f'ip:{request.meta["proxy"]}')
              if response.status == 200:
                  return response
              #代理失效小重新设置代理,并返回request重新请求
              request.meta['proxy'] = self.kuaidaili.get_ip()
              request.meta['download_timeout'] = 2
              return request
      
      
          def spider_opened(self, spider):
              spider.logger.info(f'"{spider.name}"Spide')
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
    十六、爬取腾讯招聘案例,使用自动化测试工具,需安装scrapy、pymysql、loguru、fake_useragent、selenium、scrapeops-scrapy、requests

    1.运行命令创建项目:scrapy startproject seleniumScrapySpider
    2.进入项目目录:cd .\seleniumScrapySpider
    3.运行命令创建爬虫:scrapy genspider seleniumTxWork careers.tencent.com
    4.目录结构说明
    ```
    |-- scrapySpider 项目目录

    |   |-- scrapySpider 项目目录
    |   |   |-- spiders 爬虫文件目录
    |   |   |   |-- seleniumTxWork.py 爬虫文件
    
    |   |   |-- items.py 定义数据模型文件,类似于数据库表的模式或数据结构的定义
    |   |   |-- middlewares.py 定义中间件文件,用于对请求和响应进行处理和修改
    |   |   |-- pipelines.py 定义数据处理管道(Pipeline)文件,用于处理爬取到的数据的组件
    |   |   |-- settings.py 定义配置文件,用于配置 Scrapy 项目的各种设置选项和参数
    |   |-- scrapy.cfg 框架中的配置文件,用于指定项目的结构和元数据信息
    ```
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    5.设置全局chrome驱动,把chrome驱动文件复制到miniconda根目录,不设置驱动运行程序会报“‘chromedriver’ executable needs to be in PATH”错误
    6.创建快代理文件scrapySpider>kuaidaili.py:https://www.kuaidaili.com/
    ```
    import requests

    class Kuaidaili():
        request_url = {
            # 获取代理ip前面
            'getIpSignature': 'https://auth.kdlapi.com/api/get_secret_token',
            # 获取代理ip
            'getIp': 'https://dps.kdlapi.com/api/getdps?secret_id=oy2q5xu76k4s8olx59et&num=1&signature={}'
        }
    
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36'
        }
    
        ip_use = '购买代理用户名'
        ip_password = '购买代理密码'
    
        def __init__(self):
            '''创建request会话对象'''
            self.request_session = requests.Session()
            self.request_session.headers.update(self.headers)
    
        # 获取代理ip签名
        @classmethod
        def get_ip_url(cls):
            par = {
                'secret_id': 'oy2q5xu76k4s8olx59et',
                'secret_key': '5xg6gvouc0vszfw0kxs1a8vrw1r6ity7'
            }
            response = requests.post(cls.request_url['getIpSignature'],data=par)
            response_data = response.json()
            return cls.request_url['getIp'].format(response_data['data']['secret_token'])
    
        @classmethod
        def get_ip(cls):
            url = cls.get_ip_url()
            response = requests.get(url)
            return f'http://{cls.ip_use}:{cls.ip_password}@{response.text}/'
    
    if __name__ == '__main__':
        kuaidaili = Kuaidaili()
        print(kuaidaili.get_ip())
    ```
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    7.爬取腾讯招聘案例

    • seleniumTxWork.py
      import scrapy
      import scrapy.cmdline
      from scrapy.http import HtmlResponse, Request
      from seleniumScrapySpider.items import SeleniumScrapySpiderItem
      import loguru
      import re
      
      
      class SeleniumTxWorkSpider(scrapy.Spider):
          name = "seleniumTxWork"
          allowed_domains = ["careers.tencent.com"]
          start_urls = ["https://careers.tencent.com/search.html?index={}&keyword=python"]
      
          def parse(self, response: HtmlResponse, **kwargs):
              work_list = response.xpath('//div[@class="recruit-list"]')
              reg = re.compile(r'\n|\s')
              for work in work_list:
                  work_item = SeleniumScrapySpiderItem()
                  work_item['workName'] = re.sub(reg, '',
                                                 work.xpath('.//span[@class="job-recruit-title"]/text()').extract_first())
                  work_item['workAddress'] = re.sub(reg, '', work.xpath(
                      './/span[@class="job-recruit-location"]/text()').extract_first())
                  work_item['workResponsibility'] = re.sub(reg, '',
                                                           work.xpath('.//p[@class="recruit-text"]/text()').extract_first())
                  work_item['workYearsName'] = re.sub(reg, '', work.xpath(
                      './/p[@class="recruit-tips"]/span[5]/text()').extract_first())
                  yield work_item
              '''根据分页总数获取其他页数据'''
              page_total = int(response.xpath('//ul[@class="page-list"]/li[last() - 1]/span/text()').extract_first())
              active_page = int(
                  response.xpath('//ul[@class="page-list"]/li[@class="page-li active"]/span/text()').extract_first())
              if page_total != active_page:
                  active_page += 1
                  loguru.logger.info(f'******************总页数{page_total},开始抓取第 {active_page} 页数据******************')
                  yield Request(url=self.start_urls[0].format(active_page))
              else:
                  loguru.logger.info('******************数据已全部抓取完毕******************')
      
          def start_requests(self):
              loguru.logger.info('******************开始抓取第 1 页数据******************')
              yield Request(url=self.start_urls[0].format(1))
              '''获取固定页数数据'''
              # for i in range(1,6):
              #     loguru.logger.info(f'******************开始抓取第 {i} 页数据******************')
              #     yield Request(url=self.start_urls[0].format(i))
      
      
      if __name__ == '__main__':
          scrapy.cmdline.execute('scrapy crawl seleniumTxWork'.split())
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
    • settings.py
      # Scrapy settings for seleniumScrapySpider project
      #
      # For simplicity, this file contains only settings considered important or
      # commonly used. You can find more settings consulting the documentation:
      #
      #     https://docs.scrapy.org/en/latest/topics/settings.html
      #     https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
      #     https://docs.scrapy.org/en/latest/topics/spider-middleware.html
      
      BOT_NAME = "seleniumScrapySpider"
      
      SPIDER_MODULES = ["seleniumScrapySpider.spiders"]
      NEWSPIDER_MODULE = "seleniumScrapySpider.spiders"
      #需要换上自己SCRAPEOPS中的key
      SCRAPEOPS_API_KEY = 'b0a936d4-762b-4270-9e87-a2883c2a683e'
      
      # Crawl responsibly by identifying yourself (and your website) on the user-agent
      # USER_AGENT = "seleniumScrapySpider (+http://www.yourdomain.com)"
      
      # Obey robots.txt rules
      ROBOTSTXT_OBEY = False
      
      # Configure maximum concurrent requests performed by Scrapy (default: 16)
      # CONCURRENT_REQUESTS = 32
      
      # Configure a delay for requests for the same website (default: 0)
      # See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
      # See also autothrottle settings and docs
      # DOWNLOAD_DELAY = 3
      # The download delay setting will honor only one of:
      # CONCURRENT_REQUESTS_PER_DOMAIN = 16
      # CONCURRENT_REQUESTS_PER_IP = 16
      
      # Disable cookies (enabled by default)
      # COOKIES_ENABLED = False
      
      # Disable Telnet Console (enabled by default)
      # TELNETCONSOLE_ENABLED = False
      
      # Override the default request headers:
      DEFAULT_REQUEST_HEADERS = {
          "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
          "Accept-Language": "en",
      }
      
      # Enable or disable spider middlewares
      # See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
      # SPIDER_MIDDLEWARES = {
      #    "seleniumScrapySpider.middlewares.SeleniumscrapyspiderSpiderMiddleware": 543,
      # }
      
      # Enable or disable downloader middlewares
      # See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
      DOWNLOADER_MIDDLEWARES = {
          "seleniumScrapySpider.middlewares.SeleniumDownloaderMiddleware": 543,
          'scrapeops_scrapy.middleware.retry.RetryMiddleware': 550,
      }
      
      # Enable or disable extensions
      # See https://docs.scrapy.org/en/latest/topics/extensions.html
      EXTENSIONS = {
          'scrapeops_scrapy.extension.ScrapeOpsMonitor': 500,
      }
      
      # Configure item pipelines
      # See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
      ITEM_PIPELINES = {
          "seleniumScrapySpider.pipelines.MysqlPipeLine": 300,
      }
      
      # Enable and configure the AutoThrottle extension (disabled by default)
      # See https://docs.scrapy.org/en/latest/topics/autothrottle.html
      # AUTOTHROTTLE_ENABLED = True
      # The initial download delay
      # AUTOTHROTTLE_START_DELAY = 5
      # The maximum download delay to be set in case of high latencies
      # AUTOTHROTTLE_MAX_DELAY = 60
      # The average number of requests Scrapy should be sending in parallel to
      # each remote server
      # AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
      # Enable showing throttling stats for every response received:
      # AUTOTHROTTLE_DEBUG = False
      
      # Enable and configure HTTP caching (disabled by default)
      # See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
      # HTTPCACHE_ENABLED = True
      # HTTPCACHE_EXPIRATION_SECS = 0
      # HTTPCACHE_DIR = "httpcache"
      # HTTPCACHE_IGNORE_HTTP_CODES = []
      # HTTPCACHE_STORAGE = "scrapy.extensions.httpcache.FilesystemCacheStorage"
      
      # Set settings whose default value is deprecated to a future-proof value
      REQUEST_FINGERPRINTER_IMPLEMENTATION = "2.7"
      TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
      FEED_EXPORT_ENCODING = "utf-8"
      
      # 日志配置
      LOG_FILE = 'log.log'
      LOG_FILE_APPEND = False
      LOG_LEVEL = 'INFO'
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
      • 75
      • 76
      • 77
      • 78
      • 79
      • 80
      • 81
      • 82
      • 83
      • 84
      • 85
      • 86
      • 87
      • 88
      • 89
      • 90
      • 91
      • 92
      • 93
      • 94
      • 95
      • 96
      • 97
      • 98
      • 99
      • 100
      • 101
    • 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 SeleniumScrapySpiderItem(scrapy.Item):
         workName = scrapy.Field()
         workAddress = scrapy.Field()
         workResponsibility = scrapy.Field()
         workYearsName = scrapy.Field()
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
    • 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
      import loguru
      
      class MysqlPipeLine:
      
          def open_spider(self, spider):
              self.spider = spider
              self.mysql = pymysql.connect(host='localhost',port=3306,user='root',password='root')
              self.cursor = self.mysql.cursor()
              self.create_db('job')
      
          '''创建数据库'''
          def create_db(self,db_name):
               sql = f'''CREATE DATABASE IF NOT EXISTS {db_name}'''
               try:
                   self.cursor.execute(sql)
                   self.mysql.select_db(db_name)
                   self.create_job_table()
               except Exception as e:
                   loguru.logger.info(f'创建{db_name}数据库失败:{e}')
      
          '''创建表'''
          def create_job_table(self):
              sql = '''
                   CREATE TABLE IF NOT EXISTS txWork(
                          workId INT AUTO_INCREMENT,
                          workName VARCHAR(255),
                          workAddress VARCHAR(255),
                          workResponsibility TEXT,
                          workYearsName VARCHAR(255),
                          PRIMARY KEY(workId)        
                  )
                 '''
              try:
                  self.cursor.execute(sql)
              except Exception as e:
                  loguru.logger.info(f'创建TxWork表失败:{e}')
      
          def process_item(self, item, spider):
              sql = f'''INSERT INTO txWork(workName,workAddress,workResponsibility,workYearsName) VALUES(%(workName)s,%(workAddress)s,%(workResponsibility)s,%(workYearsName)s)'''
              try:
                  self.cursor.execute(sql, dict(item))
                  self.mysql.commit()
                  loguru.logger.info(f'”{item["workName"]}”插入成功')
              except Exception as e:
                  loguru.logger.info(f'”{item["workName"]}”插入失败:{e}')
                  self.mysql.rollback()
              return item
      
          def close_spider(self,spider):
              self.mysql.close()
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
    • 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
      from scrapy.http import HtmlResponse
      from selenium.webdriver import Chrome,ChromeOptions
      from selenium.webdriver.support.wait import WebDriverWait
      from selenium.webdriver.support import expected_conditions
      from selenium.webdriver.common.by import By
      from fake_useragent import UserAgent
      from seleniumScrapySpider.kuaidaili import Kuaidaili
      import loguru
      
      # useful for handling different item types with a single interface
      from itemadapter import is_item, ItemAdapter
      
      
      class SeleniumDownloaderMiddleware:
      
          def __init__(self):
              chrome_options = ChromeOptions()
              chrome_options.add_experimental_option('detach', True)  # 不自动关闭浏览器
              chrome_options.add_experimental_option('excludeSwitches',['enable-automation'])  # 以开发者模式启动调试chrome,可以去掉提示受到自动软件控制
              chrome_options.add_experimental_option('useAutomationExtension', False)  # 去掉提示以开发者模式调用
              chrome_options.add_argument('--start-maximized')  # 最大化运行(全屏窗口)
              self.browser = Chrome(options=chrome_options)
              self.ua = UserAgent()
              self.kuaidaili = Kuaidaili()
              #初始化一个代理ip
              self.first_ip = self.kuaidaili.get_ip()
      
          @classmethod
          def from_crawler(cls, crawler):
              # This method is used by Scrapy to create your spiders.
              s = cls()
              crawler.signals.connect(s.spider_closed, signal=signals.spider_closed)
              return s
      
          def process_request(self, request, spider):
              # 设置UA
              request.headers['User-Agent'] = self.ua.random
              # 设置代理
              request.meta['proxy'] = self.first_ip
              request.meta['download_timeout'] = 5
              return None
      
          def process_response(self, request, response, spider):
              loguru.logger.info(f'代理ip:{request.meta["proxy"]}')
              if response.status == 200:
                  self.browser.get(request.url)
                  wait = WebDriverWait(self.browser, 10)  # 设置等待时间10s
                  wait.until(expected_conditions.presence_of_element_located((By.CLASS_NAME,'recruit-list')))  # 设置判断条件:等待id='kw'的元素加载完成
                  return HtmlResponse(url=request.url,body=self.browser.page_source,encoding='utf-8',request=request)
      
              # 代理失效小重新设置代理,并返回request重新请求
              request.meta['proxy'] = self.kuaidaili.get_ip()
              request.meta['download_timeout'] = 2
              return request
      
          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
      
          def spider_closed(self, spider):
              self.browser.close()
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
      • 59
      • 60
      • 61
      • 62
      • 63
      • 64
      • 65
      • 66
      • 67
      • 68
      • 69
      • 70
      • 71
      • 72
      • 73
      • 74
  • 相关阅读:
    【JAVA】-- setBorder
    如何写一份完整的职业规划书?
    linux系统sh脚本后台执行
    javacc之路1--- Token Manager
    nacos注册中心集群
    灵境:为每个一需要的人配上一个后台
    OFD文件打开教程
    【附源码】计算机毕业设计SSM汽车交易平台
    算法——回溯法(1)
    spring 循环依赖以及解决方式
  • 原文地址:https://blog.csdn.net/randy521520/article/details/133586934