使用bs4爬取Fortinet合作伙伴目录无输出结果问题求助
问题背景
需要爬取Fortinet西班牙区合作伙伴目录的三类信息:企业名称、联系电话、官方网站。目标入口地址为:https://partnerportal.fortinet.com/directory/search?l=Spain&p=1
URL中&p=1为页码参数,目录总共有92页内容。基于requests+BeautifulSoup编写的爬虫运行后print语句无任何输出,无法获取目标页面信息,原始代码如下:
import datetime import requests from bs4 import BeautifulSoup import csv filename = "fichero" + datetime.datetime.now().strftime("%d-%m-%Y")+".csv" with open(filename, "w+") as f: writer = csv.writer(f) writer.writerow(["Nombre Empresa", "Direccion Empresa", "Telefono Empresa"]) for i in range(1,3): r = requests.get('https://partnerportal.fortinet.com/directory/search?l=Spain&p='+format(i)) soup = BeautifulSoup(r.text, "html.parser") array_title = soup.select('div.panel panel-default div.col-sm-10 h3') array_address = soup.select('div.panel panel-default p.locator-partner-info') array_webpage = soup.find_all('a', class_='locator-parter-site', text=True) for iterator in range(0, len(array_title)): title = array_title[iterator].text.strip() for iterator2 in range(0, len(array_address)): address = array_address[iterator2].text.strip() print(title) print(address)
故障原因
- CSS选择器语法错误:
select()方法中写的div.panel panel-default不符合CSS选择器规则,多类名匹配需要用.连接类名,加空格代表匹配后代元素,该写法匹配不到任何节点,导致存储标题、地址的列表为空,后续循环根本不会执行,自然没有输出。 - 缺少请求头伪装:直接用requests默认请求头发送请求,会被站点反爬策略识别为爬虫程序,返回的页面不包含有效业务数据。
- 代码逻辑缺陷:两个独立循环分别遍历标题、地址列表,即使能拿到数据也会出现数据错位;循环内仅反复覆盖变量,没有做条目级的数据关联,最终打印的只会是最后一个标题,无法和地址一一对应;缺失官网字段采集、CSV写入、全页码遍历的逻辑。
- 部分场景下该站点列表数据为前端异步加载,静态HTML中不包含目标数据,直接请求静态页无法拿到内容。
修复方案
- 补全浏览器请求头,模拟正常用户访问绕过基础反爬。
- 修正CSS选择器写法,多类名匹配用
.拼接,先提取每个企业的外层容器,再在容器内提取对应字段,避免数据错位。 - 调整循环逻辑,按单个企业条目绑定名称、地址、电话、官网信息,补全全页遍历、字段拆分、CSV写入、请求延时的逻辑。
- 如果静态HTML请求始终拿不到数据,打开浏览器开发者工具抓包找到前端拉取列表的异步接口,直接请求接口拿结构化JSON数据,解析效率和稳定性更高。
修复后的可运行参考代码:
import datetime import requests from bs4 import BeautifulSoup import csv import time # 模拟浏览器请求头 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" } filename = "fichero" + datetime.datetime.now().strftime("%d-%m-%Y")+".csv" # 增加utf-8编码避免CSV乱码 with open(filename, "w+", encoding="utf-8-sig", newline="") as f: writer = csv.writer(f) # 补全官网列 writer.writerow(["企业名称", "企业地址", "联系电话", "官方网站"]) # 遍历全部92页 for i in range(1, 93): print(f"正在采集第{i}页数据") r = requests.get(f'https://partnerportal.fortinet.com/directory/search?l=Spain&p={i}', headers=headers) soup = BeautifulSoup(r.text, "html.parser") # 先提取所有企业条目外层容器 items = soup.select('div.panel.panel-default') for item in items: # 逐字段提取,做空值兼容避免报错 title = item.select_one('div.col-sm-10 h3').text.strip() if item.select_one('div.col-sm-10 h3') else "" raw_info = item.select_one('p.locator-partner-info').text.strip() if item.select_one('p.locator-partner-info') else "" # 拆分地址和电话 address = raw_info tel = "" if "Tel:" in raw_info: address, tel = raw_info.split("Tel:", 1) address = address.strip() tel = tel.strip() # 提取官网地址 web_tag = item.select_one('a.locator-parter-site') webpage = web_tag['href'] if web_tag else "" # 打印验证 print(title) print(f"地址:{address},电话:{tel},官网:{webpage}") # 写入CSV writer.writerow([title, address, tel, webpage]) # 加1秒延时,避免请求过快被封禁 time.sleep(1)
内容的提问来源于stack exchange,提问作者Rubentio322
相关产品推荐
相关产品推荐

