Scrapy爬虫XPath提取电话号码返回空值问题咨询
Scrapy提取展商手机号无返回结果排查及修复
现有问题定位
原有代码运行后拿不到手机号,核心问题有3个:
- 详情页请求未做JS渲染:列表页用了
SeleniumRequest加载动态内容,但跳详情页时用的是Scrapy原生Request,这类请求只会返回未执行JS的初始静态源码,目标站的展商联系方式是前端JS渲染填充的,静态源码里根本没有对应DOM节点,XPath自然匹配不到任何内容。 - XPath容错性极差:现有XPath写死了class属性为完全匹配
dib ml3 mr3,只要页面源码里class的空格数量、顺序变动,或者新增了其他适配类名,就会直接匹配失败;同时硬编码取第3个同class li节点的逻辑非常脆弱,只要页面前置节点数量变动,取到的内容就不是手机号。 - 取值逻辑缺失:现有XPath只定位到li标签本身,没有提取标签内的文本内容,就算匹配到节点,返回的也是整个li标签的HTML字符串,不是纯手机号内容。
修复步骤
- 统一请求方式:所有展商详情页的请求替换为
SeleniumRequest,设置合理等待时间,等页面JS执行完成、DOM节点渲染完毕后再进入解析逻辑。 - 优化XPath规则:放弃class全匹配、位置硬编码的写法,改用
contains匹配class属性,同时根据手机号的链接特征(tel:开头的跳转链接)定位节点,稳定性更高。 - 补全文本提取逻辑:定位到目标节点后提取文本内容,统一做去空白等格式化处理。
修正后完整代码
import scrapy from scrapy_selenium import SeleniumRequest import pandas as pd class TestSpider(scrapy.Spider): name = 'test' def start_requests(self): yield SeleniumRequest( url="https://aaos22.mapyourshow.com/8_0/explore/exhibitor-gallery.cfm?featured=false", wait_time=3, callback=self.parse, dont_filter=True ) def parse(self, response): # 列表页XPath同步优化,用contains匹配class避免换行、空格变动导致匹配失败 exhibitor_links = response.xpath("//h3[contains(@class,'card-Title')]//a/@href").extract() for link in exhibitor_links: full_url = response.urljoin(link) # 详情页改用SeleniumRequest加载动态内容 yield SeleniumRequest( url=full_url, wait_time=2, callback=self.parse_exhibitor_detail, dont_filter=True ) def parse_exhibitor_detail(self, response): # 基于tel:链接特征匹配手机号,不受class变动、节点位置变动影响 phone = response.xpath("//li[contains(@class,'dib')]/a[starts-with(@href,'tel:')]/text()").get() if phone: phone = phone.strip() print(phone)
注:代码里移除了没有实际调用的冗余导入,减少不必要的资源占用。
内容的提问来源于stack exchange,提问作者Amen Aziz
相关产品推荐
相关产品推荐

