通义千问1.5-1.8B-Chat-GPTQ-Int4 WebUI实战:爬虫数据清洗与信息摘要生成
本文介绍了如何在星图GPU平台上自动化部署通义千问1.5-1.8B-Chat-GPTQ-Int4 WebUI镜像,并利用该模型高效处理爬虫数据。通过设计有效的Prompt,该方案能自动化完成数据清洗与信息摘要生成,例如从杂乱的新闻或商品页面中提取结构化信息,显著提升数据处理效率。
通义千问1.5-1.8B-Chat-GPTQ-Int4 WebUI实战:爬虫数据清洗与信息摘要生成
你是不是也遇到过这种情况?辛辛苦苦写了个爬虫,吭哧吭哧跑了一晚上,结果拿到的数据乱七八糟——正文里混着广告、重复内容一大堆、关键信息散落在各个角落,整理起来比爬数据还累。
我之前处理一个新闻网站的数据,爬下来几千条,光是人工筛选和整理摘要就花了两天时间,眼睛都快看花了。后来我发现,其实这种重复性高、规则性强的文本处理工作,交给合适的大语言模型来做,效率能提升几十倍。
今天我就跟你分享一下,怎么用通义千问1.5-1.8B-Chat这个轻量级模型,通过WebUI来搞定爬虫数据的清洗和摘要生成。这个模型虽然参数不大,但处理这类结构化信息提取任务特别合适,而且经过GPTQ-Int4量化后,对硬件要求很低,普通电脑就能跑起来。
1. 为什么用大模型处理爬虫数据?
你可能觉得,爬虫数据清洗用正则表达式或者写点规则不就行了吗?确实,对于结构非常规整的网站,传统方法很有效。但现实情况往往更复杂。
我最近处理过一个电商商品页面,不同商家的描述格式千差万别。有的把价格放在“售价:”后面,有的写“价格:”,还有的直接写“¥99”。用规则去匹配,得写一堆正则,还经常漏掉一些变体。更麻烦的是,有些页面会有“推荐商品”、“看了又看”这种模块,爬下来的数据里混着不相关的内容。
这时候大模型的优势就体现出来了。它不需要你告诉它价格可能出现在哪些关键词后面,它自己能从上下文中理解什么是价格。你只需要告诉它:“从这段文本里提取商品名称、价格和主要特点”,它就能给你整理得明明白白。
通义千问1.5-1.8B-Chat这个版本,在信息提取和摘要生成上表现不错,关键是它比较“听话”——你让它输出JSON格式,它基本上就会按JSON格式来,这对于后续的数据入库特别友好。
2. 环境准备与WebUI部署
先说说怎么把这个模型跑起来。我选择的是GPTQ-Int4量化版本,这个版本在几乎不损失精度的情况下,把模型大小压缩了很多,运行起来内存占用小,速度也快。
2.1 基础环境搭建
如果你已经有Python环境,安装起来很简单。我建议用conda创建一个独立环境,避免包冲突。
# 创建并激活环境
conda create -n qwen_clean python=3.10
conda activate qwen_clean
# 安装基础依赖
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 # 根据你的CUDA版本调整
pip install transformers accelerate
2.2 WebUI部署与模型加载
现在有很多现成的WebUI框架可以用,我比较喜欢用Gradio,它简单直观,部署也方便。
# webui_demo.py
import gradio as gr
from transformers import AutoModelForCausalLM, AutoTokenizer
import torch
# 加载模型和分词器
model_name = "Qwen/Qwen1.5-1.8B-Chat-GPTQ-Int4"
tokenizer = AutoTokenizer.from_pretrained(model_name)
model = AutoModelForCausalLM.from_pretrained(
model_name,
torch_dtype=torch.float16,
device_map="auto"
)
def chat_with_model(message, history):
# 构建对话格式
messages = [
{"role": "system", "content": "你是一个专业的数据处理助手,擅长从文本中提取结构化信息和生成简洁摘要。"},
{"role": "user", "content": message}
]
# 应用聊天模板
text = tokenizer.apply_chat_template(
messages,
tokenize=False,
add_generation_prompt=True
)
# 生成回复
inputs = tokenizer(text, return_tensors="pt").to(model.device)
with torch.no_grad():
outputs = model.generate(**inputs, max_new_tokens=512)
response = tokenizer.decode(outputs[0][inputs.input_ids.shape[1]:], skip_special_tokens=True)
return response
# 创建Gradio界面
demo = gr.ChatInterface(
fn=chat_with_model,
title="通义千问数据清洗助手",
description="输入爬虫获取的原始文本,我会帮你提取关键信息和生成摘要"
)
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)
运行这个脚本,在浏览器打开 http://localhost:7860 就能看到Web界面了。界面很简洁,左边是聊天区域,右边可以调整一些参数。
第一次运行会下载模型,大概需要3-4GB的磁盘空间。下载完成后,后续启动就很快了。在我的GTX 3060笔记本上,生成一段摘要大概需要2-3秒,完全能满足批量处理的需求。
3. 设计有效的Prompt模板
用大模型处理数据,最关键的就是Prompt设计。设计得好,模型输出稳定可靠;设计得不好,每次输出格式都不一样,后续处理就麻烦了。
3.1 信息提取Prompt设计
对于爬虫数据清洗,我通常设计两种类型的Prompt:一种是提取特定字段,另一种是自由提取关键信息。
先看个商品信息提取的例子:
def extract_product_info(raw_text):
prompt = f"""
请从以下商品描述文本中提取结构化信息,并以JSON格式输出。
要求:
1. 提取商品名称、价格、主要特点、适用场景
2. 价格统一转换为数字格式(如:99.00)
3. 主要特点提取3-5个关键点
4. 如果某个信息不存在,对应字段值为null
文本内容:
{raw_text}
请输出JSON格式:
{{
"product_name": "商品名称",
"price": 价格数字,
"features": ["特点1", "特点2", "特点3"],
"scenarios": ["场景1", "场景2"]
}}
"""
return prompt
这个Prompt有几个设计要点:
- 明确输出格式:直接告诉模型要输出JSON,并给出具体格式
- 字段说明清晰:每个字段要提取什么内容都说清楚
- 处理边界情况:明确说明信息不存在时怎么处理
- 格式要求具体:比如价格要转成数字,特点要列表形式
实际使用时,你可以根据你的数据特点调整字段。比如处理新闻数据时,字段可能是“标题”、“发布时间”、“作者”、“正文摘要”、“关键词”。
3.2 摘要生成Prompt设计
对于长文本摘要,Prompt设计要引导模型抓住重点,而不是简单截取开头几句。
def generate_summary(long_text, summary_length="medium"):
length_map = {
"short": "50字左右",
"medium": "100-150字",
"long": "200-300字"
}
prompt = f"""
请为以下文本生成一个简洁的摘要。
要求:
1. 摘要长度:{length_map[summary_length]}
2. 抓住核心内容和关键信息
3. 保持客观,不要添加个人观点
4. 语言流畅,逻辑连贯
文本内容:
{long_text}
摘要:
"""
return prompt
我发现在摘要生成时,明确指定字数范围很重要。只说“简洁摘要”,模型可能生成30字也可能生成300字。指定了字数范围,输出就稳定多了。
3.3 批量处理与格式统一
爬虫数据往往是成批的,我们需要确保每一条数据的处理结果格式一致。这里有个小技巧:在Prompt里加入示例。
def batch_extract_template():
prompt = """
你是一个数据提取专家。请从每条文本中提取公司名称、成立时间和主营业务。
输出格式要求:
每条结果以JSON格式输出,多个结果用两个换行符分隔。
示例:
输入:阿里巴巴集团成立于1999年,主要业务包括电子商务、云计算、数字媒体等。
输出:{"company_name": "阿里巴巴集团", "found_year": 1999, "main_business": ["电子商务", "云计算", "数字媒体"]}
输入:腾讯公司于1998年成立,是一家互联网综合服务提供商。
输出:{"company_name": "腾讯公司", "found_year": 1998, "main_business": ["互联网综合服务"]}
现在请处理以下文本:
"""
return prompt
给模型一两个示例,它就能很好地理解你想要什么格式。这对于批量处理特别有用,能保证所有输出都是统一的JSON,方便后续用Python直接解析成字典列表。
4. 实战:新闻数据清洗与摘要
我最近用这个流程处理了一批科技新闻数据,效果很不错。跟你分享一下具体怎么操作。
4.1 原始数据示例
爬虫抓取的数据通常长这样:
【最新消息】苹果公司今日凌晨发布全新iPhone 16系列手机,起售价7999元。这款手机搭载了最新的A18芯片,性能提升30%。同时,电池续航也有显著改善,据称可支持全天候使用。发布时间:2024年9月10日。作者:科技快讯。标签:苹果, iPhone, 手机发布。
相关阅读:安卓手机市场最新动态...(这里是无关的推荐内容)
网友评论:我觉得价格太贵了...(这里是评论内容)
我们需要从这里面提取出核心信息,并过滤掉无关内容。
4.2 完整处理流程
我写了一个完整的处理脚本,你可以参考这个思路:
import json
import re
from typing import List, Dict
import requests
class NewsProcessor:
def __init__(self, api_url="http://localhost:7860"):
self.api_url = api_url
def clean_raw_text(self, raw_text: str) -> str:
"""初步清洗,移除明显无关内容"""
# 移除“相关阅读”之后的内容
if "相关阅读:" in raw_text:
raw_text = raw_text.split("相关阅读:")[0]
# 移除“网友评论”之后的内容
if "网友评论:" in raw_text:
raw_text = raw_text.split("网友评论:")[0]
# 移除多余的空白字符
raw_text = re.sub(r'\s+', ' ', raw_text).strip()
return raw_text
def build_extraction_prompt(self, text: str) -> str:
"""构建信息提取Prompt"""
prompt = f"""
请从以下新闻文本中提取结构化信息。
要求:
1. 提取新闻标题、发布时间、作者、核心内容摘要
2. 摘要长度控制在100字左右
3. 识别并提取标签(最多5个)
4. 如果信息不存在,对应字段值为null
新闻文本:
{text}
请以JSON格式输出,包含以下字段:
- title: 新闻标题
- publish_time: 发布时间(格式:YYYY-MM-DD)
- author: 作者
- summary: 内容摘要
- tags: 标签列表
- has_price: 是否包含价格信息(true/false)
"""
return prompt
def call_model(self, prompt: str) -> str:
"""调用模型API"""
# 这里简化了,实际使用时需要根据你的WebUI接口调整
payload = {
"message": prompt,
"history": []
}
try:
response = requests.post(
f"{self.api_url}/chat",
json=payload,
timeout=30
)
response.raise_for_status()
return response.json()["response"]
except Exception as e:
print(f"API调用失败: {e}")
return None
def parse_model_response(self, response: str) -> Dict:
"""解析模型返回的JSON"""
# 尝试从响应中提取JSON部分
json_match = re.search(r'\{.*\}', response, re.DOTALL)
if json_match:
try:
return json.loads(json_match.group())
except json.JSONDecodeError:
print(f"JSON解析失败: {response}")
# 如果提取失败,返回空结构
return {
"title": None,
"publish_time": None,
"author": None,
"summary": None,
"tags": [],
"has_price": False
}
def process_news(self, raw_text: str) -> Dict:
"""处理单条新闻"""
# 1. 初步清洗
cleaned_text = self.clean_raw_text(raw_text)
# 2. 构建Prompt
prompt = self.build_extraction_prompt(cleaned_text)
# 3. 调用模型
response = self.call_model(prompt)
if not response:
return None
# 4. 解析结果
result = self.parse_model_response(response)
# 5. 添加原始文本哈希(用于去重)
import hashlib
text_hash = hashlib.md5(cleaned_text.encode()).hexdigest()[:8]
result["text_hash"] = text_hash
return result
def batch_process(self, news_list: List[str]) -> List[Dict]:
"""批量处理新闻"""
results = []
seen_hashes = set()
for i, news_text in enumerate(news_list):
print(f"处理第 {i+1}/{len(news_list)} 条新闻...")
result = self.process_news(news_text)
if result and result["text_hash"] not in seen_hashes:
seen_hashes.add(result["text_hash"])
results.append(result)
# 简单限流,避免请求过快
import time
time.sleep(0.5)
return results
# 使用示例
if __name__ == "__main__":
processor = NewsProcessor()
# 模拟一批新闻数据
sample_news = [
"【最新消息】苹果公司今日凌晨发布全新iPhone 16系列手机,起售价7999元。这款手机搭载了最新的A18芯片,性能提升30%。同时,电池续航也有显著改善,据称可支持全天候使用。发布时间:2024年9月10日。作者:科技快讯。标签:苹果, iPhone, 手机发布。",
"特斯拉宣布新款Model 3降价,现价25.99万元起。此次降价旨在提升市场竞争力,同时推出了新的自动驾驶套餐。发布时间:2024年8月15日。作者:汽车之家。",
# ... 更多新闻数据
]
results = processor.batch_process(sample_news)
# 保存结果
with open("processed_news.json", "w", encoding="utf-8") as f:
json.dump(results, f, ensure_ascii=False, indent=2)
print(f"处理完成,共处理 {len(results)} 条有效新闻")
4.3 处理效果分析
运行这个脚本,原来杂乱的爬虫数据就被整理成了干净的结构化数据。以第一条新闻为例,处理后的结果大概是这样的:
{
"title": "苹果发布全新iPhone 16系列手机",
"publish_time": "2024-09-10",
"author": "科技快讯",
"summary": "苹果公司今日发布iPhone 16系列手机,起售价7999元。新品搭载A18芯片,性能提升30%,电池续航有显著改善,支持全天候使用。",
"tags": ["苹果", "iPhone", "手机发布", "科技", "新品"],
"has_price": true,
"text_hash": "a1b2c3d4"
}
可以看到,无关的“相关阅读”和“网友评论”被过滤掉了,关键信息都被提取出来,并且格式统一。这样的数据直接就能导入数据库或者用于进一步分析。
5. 处理电商商品数据的技巧
新闻数据相对规整,电商商品页面就更复杂了。不同平台、不同商家的描述格式千差万别。我总结了一些处理这类数据的经验。
5.1 多轮对话提取
对于特别复杂的商品描述,可以用多轮对话的方式,让模型一步步提取信息。
def extract_product_details(raw_description):
"""多轮对话提取商品详情"""
# 第一轮:提取基本信息
prompt1 = f"""
请从以下商品描述中提取基本信息:
{raw_description}
请提取:
1. 商品名称
2. 品牌
3. 主要类别(如:电子产品、服装、食品等)
"""
# 假设第一轮回复是 basic_info
basic_info = call_model(prompt1)
# 第二轮:提取规格参数
prompt2 = f"""
基于之前的分析,现在请提取详细规格:
商品描述:{raw_description}
已提取的基本信息:{basic_info}
请提取:
1. 颜色/款式选项
2. 尺寸/规格参数
3. 材质/成分信息
4. 特殊功能特点
"""
# 第三轮:提取价格库存
prompt3 = f"""
现在请提取商业信息:
商品描述:{raw_description}
请提取:
1. 价格信息(当前价格、原价、折扣等)
2. 库存状态(有货/缺货/预售等)
3. 配送信息
4. 促销活动
"""
# 最后整合所有信息
final_prompt = f"""
请将以下信息整合为完整的商品数据结构:
基本信息:{basic_info}
规格参数:{specs_info}
商业信息:{commerce_info}
请输出统一的JSON格式。
"""
return call_model(final_prompt)
这种方法虽然调用次数多,但提取更准确,特别适合那些信息分散在不同段落的情况。
5.2 处理图片描述文本
很多商品页面除了文字描述,还有图片的alt文本或者图片描述。这些文本往往包含重要信息,但格式很不规范。
def process_image_descriptions(img_texts):
"""处理图片描述文本"""
prompt = f"""
以下是商品页面的图片描述文本,请从中提取有用的商品信息:
图片描述列表:
{chr(10).join(f'- {text}' for text in img_texts)}
请提取:
1. 商品的不同角度展示信息
2. 商品的实际使用场景
3. 包装或配件信息
4. 尺寸对比或参考信息
注意:忽略纯装饰性或重复的描述。
"""
return call_model(prompt)
5.3 价格信息规范化
价格信息是最重要的,但也是最混乱的。不同商家写法各异:
def normalize_price_info(price_text):
"""规范化价格信息"""
prompt = f"""
请从以下价格相关文本中提取规范化信息:
文本:{price_text}
请识别:
1. 当前售价(取最低价格)
2. 原价(如果有)
3. 折扣力度(如果有)
4. 价格单位(元/美元等)
5. 是否包邮
输出要求:
- 价格统一转换为数字(如:99.99)
- 货币单位统一为CNY
- 包邮信息转换为布尔值
"""
return call_model(prompt)
6. 性能优化与批量处理建议
当你需要处理成千上万条数据时,性能就很重要了。我总结了一些优化经验。
6.1 批量请求策略
不要一条一条地请求,可以适当批量处理:
def batch_process_texts(texts, batch_size=5):
"""批量处理文本"""
results = []
for i in range(0, len(texts), batch_size):
batch = texts[i:i+batch_size]
# 构建批量处理的Prompt
batch_prompt = "请分别处理以下文本:\n\n"
for j, text in enumerate(batch):
batch_prompt += f"文本{j+1}:\n{text}\n\n"
batch_prompt += "请为每个文本提取关键信息,输出格式为JSON列表。"
batch_result = call_model(batch_prompt)
results.extend(parse_batch_result(batch_result))
# 添加延迟,避免请求过快
time.sleep(1)
return results
6.2 缓存与去重
很多爬虫数据会有重复内容,可以先做一轮去重:
def deduplicate_texts(texts):
"""基于内容相似度去重"""
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.metrics.pairwise import cosine_similarity
# 计算文本相似度
vectorizer = TfidfVectorizer()
tfidf_matrix = vectorizer.fit_transform(texts)
similarity_matrix = cosine_similarity(tfidf_matrix)
# 找出相似度高的文本
duplicates = set()
for i in range(len(texts)):
for j in range(i+1, len(texts)):
if similarity_matrix[i][j] > 0.8: # 相似度阈值
duplicates.add(j)
# 返回去重后的文本
return [texts[i] for i in range(len(texts)) if i not in duplicates]
6.3 错误处理与重试
网络请求总会有失败的时候,要做好错误处理:
def robust_model_call(prompt, max_retries=3):
"""带重试的模型调用"""
for attempt in range(max_retries):
try:
response = call_model(prompt)
if response and validate_response(response):
return response
except Exception as e:
print(f"第{attempt+1}次尝试失败: {e}")
if attempt < max_retries - 1:
wait_time = 2 ** attempt # 指数退避
time.sleep(wait_time)
print("所有重试均失败")
return None
def validate_response(response):
"""验证响应是否有效"""
# 检查响应是否包含必要信息
required_fields = ["title", "summary"] # 根据你的需求调整
try:
data = json.loads(response)
for field in required_fields:
if field not in data:
return False
return True
except:
return False
7. 实际应用中的注意事项
在实际项目中用了一段时间,我总结了一些需要注意的地方。
7.1 Prompt设计的经验
保持一致性很重要。如果你这次让模型输出“价格”,下次让输出“售价”,虽然意思差不多,但解析起来就麻烦。最好在项目开始时就确定好字段命名规范。
给模型一些思考空间。有时候在Prompt里加一句“请仔细分析文本内容”,效果会比直接下指令好。模型需要“理解”文本,而不是简单地“匹配”关键词。
处理不确定性。爬虫数据里经常有缺失信息,要在Prompt里明确告诉模型怎么处理:“如果找不到XX信息,就输出null或空字符串”。这样能保证输出结构的一致性。
7.2 模型输出的稳定性
通义千问1.5-1.8B-Chat在格式遵循上表现不错,但也不是100%稳定。我建议:
- 后处理校验:对模型输出做一次格式校验,比如检查JSON是否能正常解析,必要字段是否存在。
- 备用方案:对于特别重要的字段,可以准备正则表达式作为备用提取方案。
- 人工审核样本:定期抽样检查,看看模型有没有什么奇怪的输出模式。
7.3 成本与效率平衡
这个模型本地部署,其实没有API调用成本,主要成本是电费和硬件折旧。但处理大量数据时,时间成本也要考虑。
我的经验是:
- 对于实时性要求不高的后台任务,可以慢慢处理
- 对于需要快速响应的场景,可以考虑先用规则过滤掉简单情况,复杂的再交给模型
- 定期评估效果,如果某些类型的文本模型处理不好,可以考虑优化爬虫,让原始数据更干净
8. 总结
用通义千问1.5-1.8B-Chat处理爬虫数据,给我的感觉是“刚刚好”。它没有大到需要昂贵的GPU,也没有小到处理不了复杂任务。对于大多数爬虫数据清洗和摘要生成的需求,它都能很好地满足。
实际用下来,最深的体会是Prompt设计真的需要花心思。同样的模型,不同的Prompt设计,效果能差好几倍。开始的时候多花点时间设计好的Prompt模板,后面批量处理时就轻松多了。
另一个感受是,这种方案特别适合处理“半结构化”数据——就是那种有点规律但又不太规整的数据。完全规整的数据用正则表达式更快,完全无结构的数据需要更大的模型,而这种半结构化的文本,用这个大小的模型处理性价比最高。
如果你也在做爬虫相关的数据清洗工作,真的建议试试这个方案。从配置环境到跑通第一个例子,一两个小时就够了。一旦流程跑通,后面就是批量处理的事情,能省下大量的手工整理时间。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐



所有评论(0)