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

Scrapy导出UTF-16编码CSV列合并问题(Python3.7+Scrapy1.6)

Scrapy阿拉伯语网站CSV导出:编码与分栏的矛盾解决

我来帮你搞定这个爬取阿拉伯语网站时遇到的CSV导出问题!你现在的困境是utf-16导出时列全混在一起,换其他编码又内容异常,这其实是Excel对不同编码的CSV解析逻辑导致的,下面给你几个实用的解决方案:

问题回顾

你用Python 3.7.1 + Scrapy 1.6.0爬取阿拉伯语网站时:

  • 设置FEED_EXPORT_ENCODING = 'utf-16'导出CSV,所有字段(Company_Name、Phone、Activity、Website、Company_Type)挤在同一列;
  • 用其他编码时,CSV能正常分栏,但阿拉伯语内容格式异常。

你的相关代码如下:

spider.py

# -*- coding: utf-8 -*-
import scrapy
from scrapy import Request
from scrapy.loader import ItemLoader
from Arabic_Companies.items import ArabicCompaniesItem
class ArabicSpider(scrapy.Spider):
    name = 'arabic'
    handle_httpstatus_all = True
    def start_requests(self):
        url = "https://www.egycompanies.com/searchAr?name=&activity=&industry_id=0"
        yield Request(url, callback=self.parse)
    def parse(self, response):
        links = response.xpath("//div[@class='f-listings-item']")
        for link in links:
            Company_Name = link.xpath(".//div/div/div/h2[@class='f-listings-item__title']/a/text()").extract_first()
            Phone = link.xpath(".//*[contains(text(),' هاتف الشركة: ')]/following-sibling::text()[1]").extract_first()
            Activity = link.xpath(".//*[contains(text(),' النشاط: ')]/following-sibling::text()[1]").extract_first()
            Website = link.xpath(".//*[contains(text(),' الموقع الإلكترونى: ')]/following-sibling::a[1]/@href").extract_first()
            Company_Type = link.xpath(".//*[contains(text(),' التصنيفات : ')]/span/text()").extract_first()
            loader = ItemLoader(item=ArabicCompaniesItem(), response=response)
            loader.add_value('Company_Name', Company_Name)
            loader.add_value('Phone', Phone)
            loader.add_value('Activity', Activity)
            loader.add_value('Website', Website)
            yield loader.load_item()

items.py

import scrapy
from w3lib.html import replace_escape_chars
from scrapy.loader.processors import MapCompose, TakeFirst
class ArabicCompaniesItem(scrapy.Item):
    Company_Name = scrapy.Field(input_processor= MapCompose(replace_escape_chars))
    Phone = scrapy.Field(input_processor= MapCompose(replace_escape_chars))
    Activity = scrapy.Field(input_processor= MapCompose(replace_escape_chars))
    Website = scrapy.Field(input_processor= MapCompose(replace_escape_chars))
    Company_Type = scrapy.Field(input_processor= MapCompose(replace_escape_chars))

settings.py

FEED_EXPORT_ENCODING = 'utf-16'
FEED_EXPORT_FIELDS = ["Company_Name", "Phone", "Activity", "Website", "Company_Type"]

示例异常数据:

Company_Name,Phone,Activity,Website,Company_Type
أورينتال لمكسبات الطعم والرائحة, 0482590882, صناعات غذائية , http://www.oriental-off.com , شركات المواد الغذائية

解决方案

方案1:用utf-8-sig编码(最便捷)

这是解决问题的最优解!utf-8-sig会自动添加UTF-8的字节顺序标记(BOM),Excel能正确识别逗号分隔符,同时阿拉伯语内容也能正常显示,完美兼顾分栏和编码正确性。

修改settings.py的编码配置:

FEED_EXPORT_ENCODING = 'utf-8-sig'
FEED_EXPORT_FIELDS = ["Company_Name", "Phone", "Activity", "Website", "Company_Type"]

导出后直接用Excel打开,就能看到正常分栏的阿拉伯语数据了。

方案2:坚持用utf-16?手动指定分隔符并正确解析

如果必须使用utf-16编码,需要调整CSV分隔符并手动告诉Excel解析规则:

  1. 修改settings.py,把分隔符换成制表符:
FEED_EXPORT_ENCODING = 'utf-16'
FEED_EXPORT_FIELDS = ["Company_Name", "Phone", "Activity", "Website", "Company_Type"]
FEED_EXPORT_CSV_DELIMITER = '\t'  # 用制表符替代逗号作为分隔符
  1. 用Excel打开文件时,不要直接双击,而是选择「数据」→「自文本/CSV」,然后手动设置:
    • 文件编码选择UTF-16
    • 分隔符选择「制表符」
      这样就能正确分栏显示数据了。

额外优化:清理数据中的干扰字符

数据里的英文逗号可能会干扰CSV的分栏逻辑,建议在items.py里添加一个清理函数,把数据中的英文逗号替换成中文逗号(或者直接删除):

import scrapy
from w3lib.html import replace_escape_chars
from scrapy.loader.processors import MapCompose, TakeFirst

def clean_commas(text):
    if text:
        return text.replace(',', ',')  # 替换英文逗号为中文逗号,避免干扰CSV分隔
    return text

class ArabicCompaniesItem(scrapy.Item):
    Company_Name = scrapy.Field(input_processor= MapCompose(replace_escape_chars, clean_commas))
    Phone = scrapy.Field(input_processor= MapCompose(replace_escape_chars, clean_commas))
    Activity = scrapy.Field(input_processor= MapCompose(replace_escape_chars, clean_commas))
    Website = scrapy.Field(input_processor= MapCompose(replace_escape_chars))  # 网址里的逗号保留
    Company_Type = scrapy.Field(input_processor= MapCompose(replace_escape_chars, clean_commas))

这个小优化能避免因为数据本身带逗号导致的列混乱问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:56:01