Python脚本爬虫CSS选择器如何用

wen 实用脚本 1

Python爬虫CSS选择器实战指南:从基础到高级用法全解析

Python脚本爬虫CSS选择器如何用

目录导读

  1. 什么是CSS选择器?为什么爬虫需要它?
  2. Python爬虫中CSS选择器的三大核心库对比
  3. 基础语法:标签、类、ID选择器实战
  4. 进阶技巧:层级、伪类、属性选择器的妙用
  5. 实战案例:用CSS选择器抓取京东商品列表
  6. 常见问题与避坑指南
  7. Q&A问答汇总

什么是CSS选择器?为什么爬虫需要它?

CSS选择器是一种用于定位HTML文档中特定元素的模式匹配规则,在Python网页爬虫中,它比XPath更直观易读,尤其适合处理结构清晰的标签化页面,要提取所有class="price"<span>元素,CSS选择器只需写span.price,而XPath则需要//span[@class=‘price’]

核心优势

  • 语法简洁,学习成本低于XPath
  • 对动态页面(如JavaScript渲染)兼容性更好(配合BeautifulSoup或Parsel)
  • 几乎所有现代爬虫库(Scrapy、Selenium、requests-html)原生支持

Python爬虫中CSS选择器的三大核心库对比

特性 BeautifulSoup4 Parsel Scrapy内置选择器
安装方式 pip install beautifulsoup4 pip install parsel 随Scrapy安装
选择器方法 soup.select(‘selector’) response.css(‘selector’) response.css(‘selector’)
性能 中等 高(基于lxml) 高(集成优化)
适用场景 小规模静态页面 中等规模、需要XPath混合 大型分布式爬虫

推荐组合

  • 初学者:BeautifulSoup4 + lxml解析器
  • 工业级:Scrapy框架(内置Parsel的CSS选择器)

基础语法:标签、类、ID选择器实战

假设HTML片段:

<div id="main">
  <p class="title">商品标题</p>
  <span class="price">¥199</span>
  <p class="description">详细描述</p>
</div>

标签选择器

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, ‘lxml’)
tags = soup.select(‘p’)  # 返回所有<p>元素

类选择器

price = soup.select(‘.price’)  # class=”price”的元素
# 支持元素限定:span.price 更精确

ID选择器

main_div = soup.select(‘#main’)  # id=”main”的元素
# 注意:ID在页面中必须唯一

组合使用

soup.select(‘div#main p.title’)  # 选择main内的类为title的p

进阶技巧:层级、伪类、属性选择器的妙用

(1) 层级选择器

  • div > p:子代选择器(仅直接子元素)
  • div p:后代选择器(所有内部元素)
  • div + p:相邻兄弟选择器(紧接div后的第一个p)

示例:抓取表格第二行数据

rows = soup.select(‘table tr:nth-child(2)’)  # 伪类选择第二行

(2) 伪类选择器

  • first-child:第一个子元素
  • last-child:最后一个
  • nth-child(2n):偶数行
  • not(.hidden):排除类为hidden的元素

案例:提取所有未隐藏的链接

links = soup.select(‘a:not(.disabled)’)

(3) 属性选择器

  • [href]:包含href属性的元素
  • a[href*=”example”]:href包含指定字符串
  • img[src$=“.jpg”]:src以.jpg结尾

实战:抓取所有外链

external_links = soup.select(‘a[href^=”https”]’)  # 以https开头

实战案例:用CSS选择器抓取京东商品列表

目标:抓取京东搜索“笔记本”的前10页商品标题、价格、链接。

代码框架(使用Scrapy):

import scrapy
class JDSpider(scrapy.Spider):
    name = ‘jd’
    start_urls = [‘https://search.jd.com/Search?keyword=笔记本&page=1’]
    def parse(self, response):
        # 商品容器:class为gl-item的div
        for item in response.css(‘div.gl-item’):
            yield {
                ‘title’: item.css(‘.p-name a::text’).get(default=‘’).strip(),
                ‘price’: item.css(‘.p-price i::text’).get(),
                ‘link’: response.urljoin(item.css(‘.p-name a::attr(href)’).get())
            }
        # 翻页:提取下一页的URL
        next_page = response.css(‘.pn-next::attr(href)’).get()
        if next_page:
            yield response.follow(next_page, self.parse)

关键点

  • :text提取文本,:attr(name)提取属性
  • 使用.get()避免None异常
  • response.urljoin()处理相对路径

常见问题与避坑指南

Q1:页面是动态加载的,CSS选择器拿不到数据?
A:需配合Selenium或requests-html启用JavaScript渲染,再使用CSS选择器。

Q2:选择器匹配到多个元素,但只想要第一个?
A:使用.get()代替.getall(),或添加first-child伪类。

Q3:属性值包含空格怎么办?
A:使用[class~=”exact”]精确匹配,或通过.get(‘class’).split()处理。

Q4:为什么.select()返回空列表?
A:常见原因:

  • 解析器未用lxml(改用soup = BeautifulSoup(html, ‘lxml’))
  • HTML标签大小写不匹配(CSS对大小写敏感)
  • 页面元素在iframe或shadow DOM中

最佳实践

  1. 先在浏览器开发者工具(F12)的Console中用$$(’selector’)测试
  2. 使用print(soup.prettify())验证HTML结构
  3. 定期更新User-Agent头,避免被反爬虫拦截

Q&A问答汇总

问:CSS选择器能否提取多个不同类的元素?
答:可以,使用逗号分隔:soup.select(‘.title, .price’)将同时匹配这两种类。

问:如何处理嵌套选择器中的空格与点号冲突?
答:用反斜杠转义或直接写属性名:例如类名foo.bar需写成[class~=”foo.bar”]

问:CSS选择器在Scrapy中比XPath慢吗?
答:实测差异极小,CSS选择器经过Parsel底层优化,在复杂定位中甚至比XPath更高效。

问:爬取过程中发现选择器突然失效怎么办?
答:大概率是网站改版了,建议:

  1. 检查页面元素类名是否变化
  2. 改用更稳定的属性选择器(如[data-id]
  3. 增加异常重试机制

问:能否在CSS选择器中加入正则表达式?
答:原生不支持,但可以配合Python的re模块对提取结果二次过滤。


通过本文的系统学习,你应该能掌握从基础到高级的CSS选择器用法。好的选择器 = 精准定位 + 容错性 + 高性能,建议在实际项目中多用浏览器调试工具验证选择器,并逐步建立自己的选择器库,如果遇到具体问题,欢迎在评论区留言讨论。

抱歉,评论功能暂时关闭!