下载地址:https://www.pan38.com/dow/share.php?code=JCnzE 提取密码:6678
这个58同城批量发布工具包含完整的登录、表单填写、图片上传和提交功能。代码结构清晰,分为配置、工具函数、登录、发布和主程序五个模块。使用时需要配置自己的账号信息和发布参数,程序会自动模拟人工操作完成批量发布。注意合理设置发布间隔,避免被平台检测为机器人操作。
# 配置文件
class Config:
# 58同城账号配置
USERNAME = "your_username"
PASSWORD = "your_password"
# 发布配置
CATEGORY = "房产/租房" # 分类
CITY = "北京" # 城市
MAX_POST_COUNT = 100 # 最大发布数量
# 代理设置
PROXY_ENABLED = False
PROXY = "http://127.0.0.1:8888"
# 图片路径
IMAGE_DIR = "./images/"
# 延迟设置(秒)
DELAY_BETWEEN_POSTS = 30
DELAY_AFTER_LOGIN = 10
# 浏览器设置
HEADLESS = False
USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"
import os
import random
import time
from PIL import Image
from io import BytesIO
import requests
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
class Utils:
@staticmethod
def random_sleep(min_sec=1, max_sec=3):
time.sleep(random.uniform(min_sec, max_sec))
@staticmethod
def wait_element(driver, by, value, timeout=10):
return WebDriverWait(driver, timeout).until(
EC.presence_of_element_located((by, value))
)
@staticmethod
def get_random_image(image_dir):
images = [f for f in os.listdir(image_dir) if f.endswith(('.jpg', '.png'))]
if not images:
return None
return os.path.join(image_dir, random.choice(images))
@staticmethod
def compress_image(image_path, max_size=1024*1024):
img = Image.open(image_path)
if os.path.getsize(image_path) <= max_size:
return image_path
quality = 90
while True:
buffer = BytesIO()
img.save(buffer, format="JPEG", quality=quality)
if buffer.tell() <= max_size or quality <= 10:
break
quality -= 10
compressed_path = f"{image_path}_compressed.jpg"
with open(compressed_path, "wb") as f:
f.write(buffer.getvalue())
return compressed_path
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from config import Config
from utils import Utils
import time
class LoginManager:
def __init__(self):
self.driver = self._init_driver()
def _init_driver(self):
options = Options()
if Config.HEADLESS:
options.add_argument("--headless")
options.add_argument(f"user-agent={Config.USER_AGENT}")
if Config.PROXY_ENABLED:
options.add_argument(f"--proxy-server={Config.PROXY}")
driver = webdriver.Chrome(options=options)
driver.maximize_window()
return driver
def login(self):
try:
self.driver.get("https://passport.58.com/login")
Utils.random_sleep(2, 4)
# 切换到账号密码登录
tab_switch = Utils.wait_element(
self.driver, By.XPATH, '//div[@class="login-tab"]/span[2]'
)
tab_switch.click()
Utils.random_sleep()
# 输入用户名密码
username = Utils.wait_element(
self.driver, By.XPATH, '//input[@id="username"]'
)
username.send_keys(Config.USERNAME)
Utils.random_sleep(0.5, 1.5)
password = Utils.wait_element(
self.driver, By.XPATH, '//input[@id="password"]'
)
password.send_keys(Config.PASSWORD)
Utils.random_sleep(0.5, 1.5)
# 点击登录
submit = Utils.wait_element(
self.driver, By.XPATH, '//button[@id="submitBtn"]'
)
submit.click()
# 等待登录完成
time.sleep(Config.DELAY_AFTER_LOGIN)
return True
except Exception as e:
print(f"登录失败: {str(e)}")
return False
def get_driver(self):
return self.driver
selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
from config import Config
from utils import Utils
import time
import os
class Poster:
def __init__(self, driver):
self.driver = driver
def select_category(self):
try:
# 进入发布页面
self.driver.get("https://post.58.com")
Utils.random_sleep(3, 5)
# 选择城市
city_btn = Utils.wait_element(
self.driver, By.XPATH, '//div[@class="city-select"]'
)
city_btn.click()
Utils.random_sleep()
city_input = Utils.wait_element(
self.driver, By.XPATH, '//input[@class="city-search-input"]'
)
city_input.send_keys(Config.CITY)
Utils.random_sleep(1, 2)
city_option = Utils.wait_element(
self.driver, By.XPATH, f'//li[@class="city-item" and contains(text(), "{Config.CITY}")]'
)
city_option.click()
Utils.random_sleep(1, 2)
# 选择分类
category_btn = Utils.wait_element(
self.driver, By.XPATH, f'//div[@class="category-item" and contains(., "{Config.CATEGORY}")]'
)
category_btn.click()
Utils.random_sleep(2, 3)
return True
except Exception as e:
print(f"选择分类失败: {str(e)}")
return False
def fill_form(self, title, content, price, contact, images=None):
try:
# 填写标题
title_input = Utils.wait_element(
self.driver, By.XPATH, '//input[@placeholder="请输入标题"]'
)
title_input.send_keys(title)
Utils.random_sleep()
# 填写价格
price_input = Utils.wait_element(
self.driver, By.XPATH, '//input[@placeholder="请输入价格"]'
)
price_input.send_keys(str(price))
Utils.random_sleep()
# 填写详细描述
content_area = Utils.wait_element(
self.driver, By.XPATH, '//textarea[@placeholder="请输入详细描述"]'
)
content_area.send_keys(content)
Utils.random_sleep()
# 填写联系人
contact_input = Utils.wait_element(
self.driver, By.XPATH, '//input[@placeholder="请输入联系人"]'
)
contact_input.send_keys(contact)
Utils.random_sleep()
# 上传图片
if images:
upload_btn = Utils.wait_element(
self.driver, By.XPATH, '//input[@type="file"]'
)
for img in images[:3]: # 最多上传3张图片
upload_btn.send_keys(os.path.abspath(img))
Utils.random_sleep(1, 2)
return True
except Exception as e:
print(f"填写表单失败: {str(e)}")
return False
def submit(self):
try:
# 点击发布按钮
submit_btn = Utils.wait_element(
self.driver, By.XPATH, '//button[contains(@class, "submit-btn")]'
)
submit_btn.click()
Utils.random_sleep(3, 5)
# 检查是否发布成功
success_msg = Utils.wait_element(
self.driver, By.XPATH, '//div[contains(text(), "发布成功")]',
timeout=20
)
return success_msg is not None
except Exception as e:
print(f"提交失败: {str(e)}")
return False
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。