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

Python爬虫:从CSV读URL爬取电话邮编导出CSV的代码报错排查

爬取URL列表提取联系方式代码修正方案

现有代码存在的核心问题

  • 多套网络请求逻辑混用:同时引入Scrapy、urllib、requests三个库的请求能力,既没有正确继承Scrapy的Spider基类实现爬虫流程,也没有统一用单套逻辑发请求,类定义外的导出代码会在爬虫未启动时直接执行,根本拿不到爬取结果
  • 变量未定义/错用:parse方法中获取了response.body赋值给s,传给BeautifulSoup的却是未声明的html变量;循环内使用row[1]['URL']但从未定义row变量;读取到的页面内容是bytes类型,直接传入正则匹配会触发类型错误;邮编匹配成功时数据存入mail_1列表,最终导出却读取zipcode_1列表,匹配到的邮编会全部丢失
  • 流程逻辑错误:start_urls是URL列表,直接传给单个Request对象会触发参数错误;创建空的DataFramedf2做遍历,循环体根本不会执行,等于所有提取逻辑完全不生效;Scrapy爬虫入口方法名应为start_requests(复数),现有写法框架不会识别启动
  • 异常与配置错误:捕获HTTPError时引用了未导入的urllib3库;SSL配置使用已被主流站点废弃的SSLv23协议,会触发握手失败;请求失败分支里直接读取未赋值的url_name变量,会触发二次报错
  • 冗余代码过多:重复导入BeautifulSoup、urlparse;导入的numpy、Scrapy全量组件完全没有被使用;最后CSV转JSON的逻辑只写了一半没有落地

精简可运行版本(适合初学者,无多余依赖)

依赖安装

先执行命令安装需要的库:

pip install pandas requests

完整代码

import re
import ssl
import pandas as pd
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.ssl_ import create_urllib3_context

# 初始化存储列表
phn_list = []
zipcode_list = []

# 配置请求头,模拟浏览器
HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36'
}

# 适配老旧SSL站点,避免证书报错
class LegacySSLAdapter(HTTPAdapter):
    def init_poolmanager(self, *args, **kwargs):
        ctx = create_urllib3_context()
        ctx.check_hostname = False
        ctx.verify_mode = ssl.CERT_NONE
        kwargs['ssl_context'] = ctx
        return super().init_poolmanager(*args, **kwargs)

# 读取urls.csv里的所有URL,URL每行一个即可,无需表头
df_urls = pd.read_csv('urls.csv', header=None)
url_list = df_urls[0].dropna().str.strip().tolist()

# 创建请求会话
session = requests.Session()
session.mount('https://', LegacySSLAdapter())

# 正则匹配规则
phone_pattern = re.compile(r'\d{3}-\d{3}-\d{4}')
zip_pattern = re.compile(r'(?<=, [A-Z]{2} )\d{5}')

# 逐个遍历URL爬取
for url in url_list:
    # 补全缺失http头的URL
    if not url.startswith(('http://', 'https://')):
        url = 'https://' + url
    current_url = url
    try:
        resp = session.get(url, headers=HEADERS, timeout=15, verify=False)
        resp.encoding = resp.apparent_encoding
        page_text = resp.text
        current_url = resp.url

        # 提取电话号码
        phones = phone_pattern.findall(page_text)
        phones = list(set(phones)) # 结果去重
        if not phones:
            phn_list.append((current_url, "No phone number found."))
        else:
            for phone in phones:
                phn_list.append((current_url, phone))

        # 提取邮编
        zipcodes = zip_pattern.findall(page_text)
        zipcodes = list(set(zipcodes)) # 结果去重
        if not zipcodes:
            zipcode_list.append((current_url, "No zipcode address found."))
        else:
            for zipcode in zipcodes:
                zipcode_list.append((current_url, zipcode))

        print(f"Finish crawl: {current_url}")

    except Exception as e:
        err_msg = f"Crawl failed: {str(e)}"
        phn_list.append((current_url, err_msg))
        zipcode_list.append((current_url, err_msg))
        print(f"Fail crawl {current_url}: {str(e)}")

# 生成结果DataFrame
df_phone = pd.DataFrame(phn_list, columns=['URL', 'Phone_No']).drop_duplicates(subset=['URL', 'Phone_No'], keep='first')
df_zip = pd.DataFrame(zipcode_list, columns=['URL', 'Zipcode']).drop_duplicates(subset=['URL', 'Zipcode'], keep='first')

# 合并结果并导出CSV
df_final = pd.merge(df_phone, df_zip, on='URL', how='outer')
df_final.to_csv('result_contact.csv', index=False, encoding='utf-8-sig')
print("Result saved to result_contact.csv")

# 导出JSON格式结果
df_final.to_json('result_contact.json', orient='records', force_ascii=False, indent=2)

使用说明

  • 把待爬取的URL存在同目录下的urls.csv文件里,每行一个URL即可,不需要设置表头
  • 爬取结果会自动存在同目录下的result_contact.csv,同时生成JSON格式结果
  • 代码自动处理了无http头的URL、SSL证书报错、请求超时、重复数据去重问题,导出的CSV用Excel打开不会乱码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 10:24:14