0

0

Scrapy CSS选择器失效:深入理解浏览器与爬虫获取HTML内容的差异

花韻仙語

花韻仙語

发布时间:2025-11-12 13:26:26

|

893人浏览过

|

来源于php中文网

原创

Scrapy CSS选择器失效:深入理解浏览器与爬虫获取HTML内容的差异

在使用scrapy进行网页抓取时,开发者常常会遇到一个令人困惑的问题:精心调试的css选择器在浏览器开发者工具中能够准确匹配元素,但在scrapy爬取时却一无所获。这通常并非选择器本身有误,而是scrapy所见的网页内容与用户在浏览器中看到的内容存在本质差异。本文将深入探讨这一现象的原因,并提供实用的方法来验证scrapy实际获取的html,从而有效解决此类问题。

1. 问题现象:CSS选择器在Scrapy中失效

考虑一个典型的场景:你正在爬取两个结构相似的页面,例如https://dicionario.priberam.org/putear和https://dicionario.priberam.org/puteares。你使用了一个CSS选择器,例如div.dp-conteudo__esquerda span.varpb,期望从中提取特定的文本。在第一个页面上,该选择器成功返回了结果,但在第二个页面上,它却返回空值。

初步检查页面源代码可能会发现,第二个页面上确实存在一个带有varpb类的span标签,甚至可能出现在不同的父级元素下,但无论如何,Scrapy似乎都无法找到它。这种不一致性让开发者感到困惑,因为理论上,只要元素存在于HTML中,选择器就应该能够匹配。

2. 根本原因:浏览器与Scrapy获取内容的差异

问题的核心在于浏览器和Scrapy处理网页内容的方式不同。

  • 浏览器行为: 当你在浏览器中访问一个网页时,浏览器不仅会下载初始HTML文档,还会解析并执行其中包含的JavaScript代码。这些JavaScript代码可能会动态地修改DOM结构、从服务器请求额外的数据(例如通过AJAX),然后将这些数据插入到页面中。因此,你在浏览器开发者工具中看到的“源代码”实际上是经过JavaScript处理和渲染后的最终DOM结构。
  • Scrapy行为: Scrapy(以及大多数传统的网络爬虫)默认情况下只负责下载服务器返回的原始HTML响应。它不会执行JavaScript代码,也不会渲染页面。这意味着,如果网页的某些内容是通过JavaScript动态加载或生成的,那么这些内容将不会出现在Scrapy获取的原始HTML中。

回到我们的例子,第二个页面https://dicionario.priberam.org/puteares上的目标span.varpb元素很可能就是通过JavaScript在页面加载完成后动态添加到DOM中的。由于Scrapy不执行JavaScript,它在抓取时就无法“看到”这个动态添加的元素,因此选择器自然会失效。而第一个页面https://dicionario.priberam.org/putear上的相应元素可能直接包含在初始HTML中,所以Scrapy能够成功获取。

立即学习前端免费学习笔记(深入)”;

3. 验证Scrapy所见内容的最佳实践

理解了原因之后,解决问题的关键就是确保你的CSS选择器是基于Scrapy实际获取到的HTML内容来编写的。以下是两种验证Scrapy所见内容的方法:

3.1 使用Scrapy Shell的view(response)命令

Scrapy Shell是一个强大的交互式环境,允许你在不运行整个爬虫的情况下测试代码和检查响应。view(response)命令可以让你在浏览器中打开Scrapy当前处理的response对象所包含的HTML内容。这能直观地展示Scrapy到底“看到了”什么。

操作步骤:

  1. 在终端中启动Scrapy Shell并fetch目标URL:
    scrapy shell 'https://dicionario.priberam.org/puteares'
  2. 在Scrapy Shell中,执行view(response):
    In [1]: view(response)

    这会打开一个新的浏览器窗口,显示Scrapy抓取到的原始HTML。你可以使用浏览器开发者工具检查这个页面,看看目标元素是否真的存在。

    Live PPT
    Live PPT

    一款AI智能化生成演示内容的在线工具。只需输入一句话、粘贴一段内容、或者导入文件,AI生成高质量PPT。

    下载

3.2 将response.text保存到本地文件

另一种更直接、更方便离线分析的方法是将Scrapy获取到的原始HTML内容保存到一个本地文件。

操作步骤:

  1. 在Scrapy Shell中fetch目标URL:

    In [2]: fetch('https://dicionario.priberam.org/putear')
    2023-12-28 00:22:01 [scrapy.core.engine] INFO: Spider opened
    2023-12-28 00:22:01 [scrapy.core.engine] DEBUG: Crawled (200)  (referer: None)
  2. 将response.text写入一个本地HTML文件:

    In [3]: with open('putear.html', 'wt', encoding='utf8') as fd:
       ...:     fd.write(response.text)
       ...:
  3. 对第二个页面重复上述步骤:

    In [4]: fetch('https://dicionario.priberam.org/puteares')
    2023-12-28 00:23:09 [scrapy.core.engine] DEBUG: Crawled (200)  (referer: None)
    
    In [5]: with open('puteares.html', 'wt', encoding='utf8') as fd:
       ...:     fd.write(response.text)
       ...:
  4. 现在,你可以在本地文件系统找到putear.html和puteares.html这两个文件。用任何文本编辑器或浏览器打开它们,检查它们的源代码。你会发现,在puteares.html中,你期望的div.dp-conteudo__esquerda span.varpb结构很可能是不存在的,或者span.varpb元素位于完全不同的位置,导致你的原始选择器失效。

4. 总结与注意事项

  • 始终验证Scrapy所见: 当CSS选择器在浏览器中有效但在Scrapy中失效时,第一步也是最重要的一步就是验证Scrapy实际获取的HTML内容。这能帮助你区分是选择器错误还是内容动态加载的问题。
  • 动态内容处理: 如果确认目标内容是通过JavaScript动态加载的,传统的Scrapy爬虫将无法直接获取。在这种情况下,你需要考虑使用能够执行JavaScript的工具,例如:
    • Scrapy Splash: 一个轻量级的JavaScript渲染服务,可以与Scrapy集成。
    • Selenium/Playwright: 浏览器自动化工具,可以模拟用户行为,等待页面加载完成并获取渲染后的HTML。
  • 选择器优化: 如果目标元素存在于Scrapy获取的HTML中,但只是位置与浏览器中看到的略有不同,那么你需要根据Scrapy实际获取的HTML结构来调整你的CSS选择器。
  • 优先级: 在调试Scrapy选择器时,优先使用response.css()或response.xpath()进行测试,而不是完全依赖浏览器开发者工具中的选择器结果,因为它们所操作的DOM可能不同。

通过理解Scrapy与浏览器在处理动态内容上的差异,并利用上述验证方法,你将能更有效地调试和开发你的Scrapy爬虫,从而避免因HTML内容不一致而导致的抓取失败。

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

554

2023.06.20

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

374

2023.07.04

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

732

2023.07.04

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

477

2023.09.01

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

394

2023.09.04

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

991

2023.09.04

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

657

2023.09.12

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

551

2023.09.20

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

27

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 2.9万人学习

CSS教程
CSS教程

共754课时 | 19.6万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号