Files
fdesk/app/command/EmailParseCommand.php
2025-08-04 14:03:57 +08:00

144 lines
4.2 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace app\command;
use support\Db;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* 将拉取邮箱的详情进行清洗,找出询盘的邮件入库(根据emai_detail)
*/
class EmailParseCommand extends Command
{
protected static $defaultName = 'email-parse';
protected static $defaultDescription = '邮件清洗';
protected function configure()
{
// 不再接收参数,固定每次 100 条
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$batchSize = 100; // 每次处理 100 条
$page = 0;
// 明确定义 parsed_contacts 表里要插入的所有列(顺序无所谓,但要全部包含)
$fields = [
'email_id',
'date',
'email',
'name',
'tel',
'company',
'country',
'form_url',
'message',
'ip',
'iplocation',
'ilang',
'mailto',
'navigator_language',
'navigator_platform',
'screen_width',
'screen_height',
'ucountry',
];
while (true) {
$rows = Db::table('emails')
->orderBy('id', 'asc')
->limit($batchSize)
->offset($page * $batchSize)
->get();
if ($rows->isEmpty()) {
break;
}
$toInsert = [];
foreach ($rows as $row) {
$parsed = $this->parseHtml($row->body);
if ($parsed === null) {
$output->writeln(" ↳ [{$row->id}] skip: not a contact-form HTML");
continue;
}
// 严格按 $fields 顺序填充每条记录,缺失的字段补 null
$record = [];
foreach ($fields as $col) {
if ($col === 'email_id') {
$record[$col] = $row->id;
} else {
$record[$col] = $parsed[$col] ?? null;
}
}
$toInsert[] = $record;
}
if (!empty($toInsert)) {
Db::table('email_parsed_result')->insert($toInsert);
$output->writeln("Inserted batch #" . ($page + 1) . ", count: " . count($toInsert));
}
$page++;
}
$output->writeln("✔ All done.");
return Command::SUCCESS;
}
/**
* 解析 HTML,找不到 <h2>Preview</h2> 则返回 null,
* 否则提取所有 <span>Key:</span> Value 为小写蛇形 key=>value 数组
*/
protected function parseHtml(string $html): ?array
{
$doc = new \DOMDocument();
libxml_use_internal_errors(true);
$doc->loadHTML('<?xml encoding="utf-8"?>' . $html);
libxml_clear_errors();
$xpath = new \DOMXPath($doc);
// 类型检查
if ($xpath->query("//h2[text()='Preview']")->length === 0) {
return null;
}
$nodes = $xpath->query("//div[span]");
$data = [];
/** @var \DOMElement $node */
foreach ($nodes as $node) {
$span = $xpath->query("span", $node)->item(0);
if (! $span) {
continue;
}
// 原始键名
$key = trim(str_replace(':', '', $span->textContent));
// 转成小写蛇形
$col = strtolower(str_replace(' ', '_', $key));
// 获取值
$a = $xpath->query(".//a", $node)->item(0);
if ($a && $a->hasAttribute('href')) {
$value = trim($a->getAttribute('href'));
} else {
$clone = $node->cloneNode(true);
$spanClone = $xpath->query(".//span", $clone)->item(0);
if ($spanClone) {
$spanClone->parentNode->removeChild($spanClone);
}
$value = trim($clone->textContent);
}
$data[$col] = $value;
}
return $data;
}
}