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

一、引言

在东南亚展会网站采集中,缅甸国际塑料橡胶展(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选择器更有效
  • 深度控制:明确爬取边界,避免陷入无限循环
  • 防御性解码:永远假设邮箱被多种方式编码

结语

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

相关推荐
core5121 小时前
多源车辆数据打通实战指南:从12123接口、爬虫获取电动自行车车辆信息到备案数据推送六合一平台
爬虫·电动自行车·12123·车辆信息·六合一·备案数据
上海云盾-小余1 小时前
CC 攻击与 DDoS 联动防护:如何构建一体化流量清洗架构
网络·安全·游戏·架构·ddos
向往着的青绿色2 小时前
雷池(SafeLine)社区版免费部署教程|从环境检查到防护实操全流程
网络·计算机网络·nginx·网络安全·容器·网络攻击模型·信息与通信
Larry_Yanan2 小时前
Qt网络开发之基于 QWebEngine 实现简易内嵌浏览器
linux·开发语言·网络·c++·笔记·qt·学习
winfredzhang2 小时前
用 Python + DeepSeek AI 构建文件批量重命名与智能管理工具
python·api·重命名·预览·解压·deepseek
西西弗Sisyphus2 小时前
Python 中__pycache__文件夹
python
qingcyb2 小时前
重复 id 对应的多个对象
开发语言·python
mingshili2 小时前
[python] asyncio常规操作记录
python·async
chushiyunen2 小时前
python edge-tts实现tts文本转语音、音频
数据库·python·音视频