Scrapy爬虫爬取Reclame Aqui投诉链接失败,如何排查并获取全部投诉?
问题:无法爬取Reclame Aqui上桑坦德的未回复投诉链接
我需要爬取网站https://www.reclameaqui.com.br/empresa/santander/lista-reclamacoes/?status=NOT_ANSWERED上的全部未回复客户投诉,编写了如下ComplaintScraper(CrawlSpider)代码:
class ComplaintScraper(CrawlSpider): name = "ComplaintScraper" allowed_domains = ["https://www.reclameaqui.com.br"] start_urls = [ "https://www.reclameaqui.com.br/empresa/santander/lista-reclamacoes/?status=NOT_ANSWERED", #Only complaints not answered ] ''' LinkExtractor: An object which defines how links will be extracted from each crawled page. ''' rules = ( Rule(LinkExtractor(restrict_css = '#__next > div.sc-1mzw716-0.bbugAk > div.sc-1mzw716-1.dAjixN > div.wydd4i-0.jaTnlr > main > ' + 'section.wydd4i-5.bDtuKO > div.sc-gJpXkD.ebMJNx.xh9b9g-0.jjQFrx > ' + 'div.sc-1sm4sxr-0.eFXbXn > div:nth-child(1) > a'), callback = "parse_complaint", follow=True), ) def start_requests(self): for url in self.start_urls: yield SplashRequest(url, self.parse_complaint, endpoint='render.html', args={'wait': 0.5}) def parse_complaint(self, response): print("Hi", response.url)
但控制台无法输出如下目标投诉链接:
https://www.reclameaqui.com.br/santander/desacordo-comercial_EDEwdRrqoHSC5Win/https://www.reclameaqui.com.br/santander/estorno-de-seguro-residencial_RsOgQiG151B-n_x8/https://www.reclameaqui.com.br/santander/do-pix_wylD_ba-c_LBOGQ2/https://www.reclameaqui.com.br/santander/veiculo-quitado_AP-e15Kmdo0zhlqd/- ...
请问我代码中的错误在哪里?如何获取该列表中的全部客户投诉?
错误分析与解决方案
1. 错误点梳理
allowed_domains格式错误:该参数仅需域名本身,不能带https://,错误格式会导致Scrapy过滤所有符合条件的链接。- 重写
start_requests破坏CrawlSpider规则逻辑:直接用SplashRequest调用parse_complaint,跳过了CrawlSpider内置的链接提取规则(rules),导致定义的Rule完全失效。 - CSS选择器脆弱且范围狭窄:使用了动态生成的类名(如
sc-1mzw716-0、bbugAk),这类类名会随网站更新变化;同时div:nth-child(1)仅匹配第一个投诉项,无法获取全部链接。 - 回调函数逻辑冲突:同一个
parse_complaint既被用作列表页回调,又被用作详情页回调,逻辑混乱。
2. 修正后的代码
from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from scrapy_splash import SplashRequest class ComplaintScraper(CrawlSpider): name = "ComplaintScraper" # 修正allowed_domains,仅保留域名 allowed_domains = ["www.reclameaqui.com.br"] start_urls = [ "https://www.reclameaqui.com.br/empresa/santander/lista-reclamacoes/?status=NOT_ANSWERED", ] # 定义链接提取规则:匹配所有投诉详情页链接,使用Splash渲染 rules = ( Rule( LinkExtractor(allow=r'/santander/[^/]+_[\w-]+/'), callback="parse_complaint", follow=True, process_request='use_splash' # 指定用Splash处理请求 ), # 分页规则:自动抓取下一页内容 Rule( LinkExtractor(restrict_css='a[aria-label="Próxima página"]'), follow=True, process_request='use_splash' ) ) def use_splash(self, request): # 封装Splash请求,确保JS渲染完成 return SplashRequest( url=request.url, endpoint='render.html', args={'wait': 2}, # 延长等待时间,保证页面加载完成 meta={'original_url': request.url} ) def parse_complaint(self, response): # 输出抓取到的详情页URL print("已抓取投诉链接:", response.url) # 可在此添加投诉内容提取逻辑,如标题、正文、日期等 # 示例: # title = response.css('h1::text').get().strip() # content = ' '.join(response.css('.complaint-description ::text').getall()).strip()
3. 关键改动说明
- 修正域名配置:
allowed_domains改为["www.reclameaqui.com.br"],避免合法链接被过滤。 - Splash与规则集成:通过
process_request在Rule中指定Splash处理请求,既保留CrawlSpider的自动爬取逻辑,又实现JS渲染。 - 稳定的链接匹配:用正则表达式
allow=r'/santander/[^/]+_[\w-]+/'匹配所有投诉详情页,比动态CSS选择器更可靠。 - 分页自动抓取:添加分页链接规则,自动遍历所有页面的未回复投诉。
- 回调逻辑分离:
parse_complaint专门处理详情页,避免逻辑混乱。
内容的提问来源于stack exchange,提问作者Fillipe
相关产品推荐
相关产品推荐

