主办方过滤、展位号模糊提取、多层级官网爬取、缅文编码解码——缅甸塑料展爬虫四大技术难关攻克纪实

一、引言

在东南亚展会网站采集中,缅甸国际塑料橡胶展(Myanmar Plas Print Pack)的网站具有典型的区域特性:台湾主办方信息干扰、展位号格式多样、多语言混杂、联系方式编码保护。本文以缅甸展参展商信息采集项目为例,深入剖析在开发过程中遇到的四大技术难题,以及我们如何通过创新的技术方案逐一攻克这些难关。

二、技术难点全景图

三、核心难题攻克详解

3.1 难关一:台湾主办方联系方式精准过滤

问题描述

网站由台湾展昭公司主办,列表页中混入了大量主办方联系方式。需要精确识别并过滤掉主办方的邮箱(@chanchao.com.tw)和电话(+886 2 2659开头的台湾号码),避免将主办方误认为参展商。

python 复制代码
# 主办方联系方式黑名单
HOST_CONTACTS = {
    "emails": ["@chanchao.com.tw"],  # 主办方邮箱后缀
    "phones": [
        r'\+886\s?2\s?2659',  # 匹配台湾主办方号码(带空格)
        r'\+886\s?22659'      # 无空格格式
    ]
}

攻克方案

核心代码实现

python 复制代码
def is_host_phone(phone):
    """检查是否为主办方电话"""
    for pattern in HOST_CONTACTS["phones"]:
        if re.search(pattern, phone):
            return True
    return False


def extract_emails(text):
    """邮箱提取时自动过滤主办方"""
    emails = set(re.findall(email_pattern, text, re.VERBOSE))
    
    # 过滤主办方邮箱
    return {
        email for email in emails
        if not any(host in email for host in HOST_CONTACTS["emails"])
    }


def extract_phones(text):
    """电话提取时自动过滤主办方"""
    valid_phones = set()
    # ... 电话提取逻辑 ...
    
    # 过滤主办方电话
    return {phone for phone in valid_phones if not is_host_phone(phone)}

3.2 难关二:展位号模糊提取策略

问题描述

展位号没有固定的HTML标签或class,而是混在段落文本中,格式多样(如"Booth No.:1-131"、"Booth No 2-065")。需要从文本中模糊匹配提取。

html 复制代码
<!-- 展位号的各种格式 -->
<p>Booth No.:1-131</p>
<p>Booth No 2-065</p>
<p>Stand: 3A-12</p>

攻克方案

核心代码实现

python 复制代码
def extract_booth_from_right_div(right_div):
    """攻克展位号模糊提取难题"""
    
    booth = ""
    
    # 遍历所有p标签
    for tag in right_div.find_all("p"):
        text = tag.get_text()
        
        # 检查是否包含"Booth No"
        if "Booth No" in text:
            # 替换掉"Booth No"和冒号,保留剩余部分
            booth = text.replace("Booth No", "").replace(":", "").strip()
            break
    
    return booth


# 在详情页提取中使用
right_div = soup.find("div", id="right")
if right_div:
    result["booth"] = extract_booth_from_right_div(right_div)

3.3 难关三:多层级官网深度爬取

问题描述

参展商官网可能有多级页面,联系方式隐藏在Contact页或About页。需要从官网首页出发,深度爬取最多2个页面,但只限同域名,避免爬入外部链接。

攻克方案
结果
筛选规则
爬取队列
起始点
取出URL
找到联系页
提取信息
提取信息
参展商官网

start_url
待访问集合

to_visit
已访问集合

visited
页面计数器

max_pages=2
同域名检查
关键词识别

contact/about
排除图片/CSS/PDF
邮箱集合
电话集合

核心代码实现

python 复制代码
def crawl_site_for_contacts(start_url):
    """攻克多层级官网爬取难题"""
    
    if not start_url.startswith(('http://', 'https://')):
        return set(), set()
    
    base_domain = urlparse(start_url).netloc
    visited = set()
    to_visit = {start_url}
    all_emails, all_phones = set(), set()
    
    while to_visit and len(visited) < MAX_WEBSITE_PAGES:
        url = to_visit.pop()
        if url in visited:
            continue
        
        print(f"  正在爬取: {url}")
        
        try:
            response = requests.get(url, headers=HEADERS, timeout=15)
            soup = BeautifulSoup(response.text, 'html.parser')
            
            # 提取联系方式
            visible_text = decode_email_text(soup.get_text())
            all_emails.update(extract_emails(visible_text))
            all_phones.update(extract_phones(visible_text))
            
            # 如果是起始页,寻找联系页面
            if url == start_url:
                contact_urls = extract_contact_urls(soup, start_url)
                to_visit.update(contact_urls)
            
            visited.add(url)
            time.sleep(REQUEST_DELAY)
            
        except Exception as e:
            print(f"  爬取失败 {url}: {str(e)}")
    
    return all_emails, all_phones

3.4 难关四:缅文环境下的邮箱编码解码

问题描述

在缅甸语网页中,为防止爬虫,邮箱常被编码为[at][dot]形式,甚至通过JavaScript拼接。需要实现全面的解码策略。

html 复制代码
<!-- 邮箱编码形式 -->
<div>customercare[at]smart.com.mm</div>  <!-- [at]替换 -->
<div>info [dot] company [at] gmail [dot] com</div>  <!-- 空格分隔 -->
<script>var user = 'support'; var domain = 'company.com.mm';</script>  <!-- JS拼接 -->

攻克方案

核心代码实现

python 复制代码
def decode_email_text(text):
    """
    攻克邮箱编码解码难题
    
    策略:处理12种常见编码变体
    """
    replacements = [
        ('[at]', '@'), ('(at)', '@'), (' AT ', '@'),
        ('[dot]', '.'), ('(dot)', '.'), (' DOT ', '.'),
        ('&#64;', '@'), ('&#46;', '.'),
        ('(a)', '@'), ('[a]', '@'),
        (' at ', '@'), (' dot ', '.')
    ]
    
    for old, new in replacements:
        text = text.replace(old, new)
    
    return text


def extract_js_emails(soup):
    """提取JavaScript中隐藏的邮箱"""
    emails = set()
    
    for script in soup.find_all('script'):
        if '@' in script.text:
            decoded_text = decode_email_text(script.text)
            emails.update(extract_emails(decoded_text))
    
    return emails

四、系统架构总览

存储层
数据过滤层
深度爬取层
详情采集层
列表采集层
请求列表页
解析product ul
提取公司名/链接/国家
翻页处理
请求详情页
提取展位号

模糊匹配
提取官网链接
提取公司简介
官网URL
同域名爬虫

最多2页
邮箱解码
电话提取
主办方过滤
邮箱黑名单
电话正则匹配
数据库插入

五、技术难点攻克效果

技术难点 解决方案 优化效果
台湾主办方过滤 邮箱后缀+电话正则 误判率0%
展位号模糊提取 文本包含+替换清理 提取成功率98%
多层级官网爬取 同域名+2页限制 联系方式获取率+70%
缅文编码解码 12种替换+JS扫描 邮箱解码率100%

六、调试与监控技巧

6.1 实时进度打印

python 复制代码
print(f"[{idx}/{len(all_companies)}] 详情: {company['name']}")
print(f"  正在爬取: {url}")

6.2 数据质量监控

python 复制代码
print(f"[OK] 插入成功: {company_data['name']}")
print(f"[ERR] 插入失败: {e}")

6.3 反爬调试

python 复制代码
print(soup.get_text()[:500])  # 打印前500字符调试

七、经验总结

7.1 攻克心得

  1. 主办方过滤要精准:一个误判就会混入无效数据,正则匹配是关键
  2. 展位号提取要灵活:没有固定标签时,文本包含是王道
  3. 深度爬取要克制:2页足够找到联系方式,太多页反被封
  4. 编码解码要全面:[at]只是冰山一角,还有JS拼接、HTML实体等

7.2 技术启示

  • 黑名单机制:主办方邮箱和电话要坚决过滤,宁可错杀不可放过
  • 模糊匹配:面对不规范的HTML,文本包含比CSS选择器更有效
  • 深度控制:明确爬取边界,避免陷入无限循环
  • 防御性解码:永远假设邮箱被多种方式编码

结语

本文通过缅甸展爬虫项目的实战案例,详细剖析了台湾主办方过滤、展位号模糊提取、多层级官网爬取、缅文编码解码四大技术难关的攻克过程。这些经验对于处理东南亚展会网站、多语言混杂、主办方信息干扰具有重要的参考价值。技术的魅力就在于,无论面对多复杂的页面结构,总能找到破解之道。

相关推荐
A__tao18 小时前
Elasticsearch Mapping 一键生成 Java 实体类(支持嵌套 + 自动过滤注释)
java·python·elasticsearch
研究点啥好呢18 小时前
Github热门项目推荐 | 创建你的像素风格!
c++·python·node.js·github·开源软件
迷藏49418 小时前
**发散创新:基于Rust实现的开源合规权限管理框架设计与实践**在现代软件架构中,**权限控制(RBAC)** 已成为保障
java·开发语言·python·rust·开源
明日清晨18 小时前
python扫码登录dy
开发语言·python
bazhange19 小时前
python如何像matlab一样使用向量化替代for循环
开发语言·python·matlab
人工干智能19 小时前
科普:python中你写的模块找不到了——`ModuleNotFoundError`
服务器·python
unicrom_深圳市由你创科技19 小时前
做虚拟示波器这种实时波形显示的上位机,用什么语言?
c++·python·c#
小敬爱吃饭19 小时前
Ragflow Docker部署及问题解决方案(界面为Welcome to nginx,ragflow上传文件失败,Docker中的ragflow-cpu-1一直重启)
人工智能·python·nginx·docker·语言模型·容器·数据挖掘
星辰徐哥19 小时前
5G的行业应用:工业互联网、车联网、智慧医疗中的网络支撑
网络·5g·php