You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

解析AJAX表格时无法提取bs4.element.Tag类型数据文本的问题

问题描述
  • 解析AJAX表格数据时,得到的数据类型为bs4.element.Tag,尝试用replace、strip等字符串处理函数无效,即使指定text属性也无法正确提取标记内文本。
  • 包含评论数的元素类名为tcl2,无法用re.sub删除类名中的“2”,因为评论数本身可能为2,会误删有效数据。

用户代码:

import requests
from bs4 import BeautifulSoup
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import json
import re
import time

catalog = {}

def parse (): 
    header = {
    'user-agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.167 YaBrowser/22.7.5.940 Yowser/2.5 Safari/537.36"
    } 
    session = requests.Session() 
    retry = Retry(connect=1, backoff_factor=0.5) 
    adapter = HTTPAdapter(max_retries=retry)
    inb = 1
    comp = 'all'
    while inb <= 1:

        url_not_based = (f"http://foodmarkets.ru/firms/filter_result/7/{comp}/0/posted/page{inb}/") 
        session.mount(f'http://foodmarkets.ru/firms/filter_result/7/{comp}/0/posted/page{inb}/'
        ,adapter)
        r = session.get (url_not_based,verify=True,headers=header,timeout=5) 
        soup = BeautifulSoup (r.text, "lxml")
        rounded_block = soup.find_all('tr')

        for round in rounded_block:

            round_сompany = round.find('td',class_='tcl'>'href')
            clear_comp1 = re.sub(r'[a-zA-Z<>/\t\n=''0-9.:"""']','',str(round_сompany))
            clear_comp2 = re.sub(r'[\xa0]',' ',clear_comp1)

            round_сity = round.find('td',class_="tc2 nowrap")
            clear_city1 = re.sub(r'[a-zA-Z<>/\t\n=''0-9.:"""']','',str(round_сity))
            clear_city2 = re.sub(r'[\xa0]',' ',clear_city1)

            round_сommment = round.find('td',class_="tc2 cntr")
            clear_comm1 = re.sub(r'[a-zA-Z<>""''/\t\n=.:]','',str( round_сommment))
             
            if round_сompany in catalog:
                continue
            else:
                catalog [round_сompany] = { 
                    "Company": clear_comp2,
                    "City":clear_city2,
                    "Comment": clear_comm1,
                }
        inb = inb+1 
        time.sleep(0.5)

 #   print (catalog)
#with open ("catalog.json","w",encoding='utf-8') as file: 
#    json.dump(catalog, file, indent=4, ensure_ascii=False) 

if __name__ == "__main__":
    parse()
解决方案

1. 正确提取bs4.element.Tag内的文本

bs4.element.Tag是BeautifulSoup的元素对象,不能直接用字符串处理函数,需用.text或.get_text()方法提取文本内容,无需通过正则暴力删除标签。同时注意代码中的语法错误:round_сompany = round.find('td',class_='tcl'>'href')是错误写法,应先定位目标td,再找到其中的<a>标签提取文本。

2. 评论数提取无需处理类名

元素类名tcl2是标记元素的属性,和元素内的评论数文本无关,直接提取该元素的文本即可,不需要对类名进行任何操作。

修正后的代码

import requests
from bs4 import BeautifulSoup
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
import json
import time

catalog = {}

def parse(): 
    header = {
        'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.167 YaBrowser/22.7.5.940 Yowser/2.5 Safari/537.36"
    } 
    session = requests.Session() 
    retry = Retry(connect=1, backoff_factor=0.5) 
    adapter = HTTPAdapter(max_retries=retry)
    # 挂载adapter到域名,而非单个URL,复用连接更高效
    session.mount('http://foodmarkets.ru', adapter)
    
    inb = 1
    comp = 'all'
    while inb <= 1:
        url_not_based = f"http://foodmarkets.ru/firms/filter_result/7/{comp}/0/posted/page{inb}/" 
        r = session.get(url_not_based, verify=True, headers=header, timeout=5) 
        soup = BeautifulSoup(r.text, "lxml")
        rounded_block = soup.find_all('tr')

        for row in rounded_block:
            # 提取公司名称:找到tcl类的td,再取其中a标签的文本
            company_td = row.find('td', class_='tcl')
            if not company_td:
                continue
            company_name = company_td.find('a').get_text(strip=True).replace('\xa0', ' ')
            
            # 提取城市:直接取tc2 nowrap类td的文本
            city_td = row.find('td', class_="tc2 nowrap")
            city_name = city_td.get_text(strip=True).replace('\xa0', ' ') if city_td else ''
            
            # 提取评论数:取tc2 cntr类td的文本
            comment_td = row.find('td', class_="tc2 cntr")
            comment_count = comment_td.get_text(strip=True) if comment_td else '0'
            
            # 用公司名称作为键,避免Tag对象作为键的潜在问题
            if company_name in catalog:
                continue
            catalog[company_name] = { 
                "Company": company_name,
                "City": city_name,
                "Comment": comment_count,
            }
        inb += 1 
        time.sleep(0.5)

    print(catalog)
    with open("catalog.json", "w", encoding='utf-8') as file: 
        json.dump(catalog, file, indent=4, ensure_ascii=False) 

if __name__ == "__main__":
    parse()

关键优化点

  • 用.get_text(strip=True)直接提取并清理文本,替代复杂正则,更可靠。
  • 修复了find方法的语法错误,正确定位元素。
  • 将session.mount挂载到域名而非单个URL,复用连接更高效。
  • 用公司名称作为字典键,避免bs4.element.Tag对象作为键的潜在问题。
  • 增加了空值判断,避免因元素不存在导致的报错。

内容的提问来源于stack exchange,提问作者Apple

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 15:00:54