从链家网爬取指定城市的二手房信息,并将数据保存为CSV文件。它使用了Selenium库来模拟浏览器行为,以便获取动态加载的页面内容。具体而言,它实现了一个名为LianJia的类,其中包含了获取房源列表和房源详情的方法。主要步骤如下:

  • 读取城市信息和代理IP信息,并初始化Chrome浏览器及其设置。
  • 定义LianJia类,其中house_list()方法用于获取指定城区的所有房源链接,house_detail()方法用于获取单个房源的详细信息。
  • run()方法用于执行爬取过程,它首先访问链家网站,然后获取指定城市的所有城区链接,再依次遍历每个城区,获取所有房源的详细信息,并保存到CSV文件中。
  • 最后,循环遍历所有城市,调用run()方法执行爬取任务。
  • 需要注意的是,这段代码在使用Selenium时需要确保已经安装好Chrome浏览器和对应版本的ChromeDriver,并将ChromeDriver的路径添加到系统环境变量中。
from selenium import webdriver
from fake_useragent import UserAgent
import random
from selenium.webdriver.common.by import By
import os
import pandas as pd
from pinyin import pinyin
import subprocess

# 读取城市信息
with open("city.txt", "r", encoding="utf-8") as file:
    cities = [line.strip() for line in file if line.strip()]

ips = []
with open('ip.txt', 'r') as f:
    for line in f:
        ip = line.strip()
        ips.append(ip.strip())

# 启动Chrome浏览器调试服务
subprocess.Popen('cmd', shell=True)
subprocess.Popen('chrome-win64\chrome.exe" --remote-debugging-port=9222', shell=True)

chrome_options = webdriver.ChromeOptions()
chrome_options.add_experimental_option("debuggerAddress", "localhost:9222")
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable‐gpu')
chrome_options.add_argument("--disable-blink-features=AutomationControlled")
chrome_options.add_argument('--proxy-server=http://' + random.choice(ips))
chrome_options.add_argument(f"user-agent={UserAgent().random}")
driver = webdriver.Chrome(options=chrome_options)

class LianJia:
    def __init__(self):
        # 声明Chrome浏览器对象, 这里填写你自己的driver路径
        self.driver = driver
        self.item = None
    def house_detail(self, item):
        """获取一间房子的详情信息"""
        self.driver.get(item['houseURL'])  # 访问一间房子的详情页

        # 获取页面上的房子信息
        item['title'] = self.driver.find_element(By.TAG_NAME, 'h1').text  # 标题
        item['price'] = self.driver.find_element(By.CSS_SELECTOR, 'span.total').text  # 价格
        house_info = self.driver.find_elements(By.CSS_SELECTOR, 'div.mainInfo')
        item['room'] = house_info[0].text  # 户型
        item['faceTo'] = house_info[1].text  # 朝向
        item['area'] = house_info[2].text  # 面积
        # 小区名
        item['communityName'] = self.driver.find_element(By.CSS_SELECTOR, 'div.communityName a.info').text
        # 发布日期
        item['releaseDate'] = self.driver.find_element(By.XPATH, '//div[@class="transaction"]/div[2]/ul/li/span[2]').text
        
        
    def house_list(self, item):
        """获取一个城区中所有房子的详情页链接"""
        # 访问城区的页面
        self.driver.get(item['partURL'])
        # 切换到'最新发布'页面
        self.driver.find_element(By.LINK_TEXT, '最新发布').click()
        # 获取到所有的房子链接
        house_ls = self.driver.find_elements(By.XPATH, '//ul[@class="sellListContent"]//div[@class="title"]/a')
        # 生成url列表
        house_url_ls = [house.get_attribute("href") for house in house_ls]

        
        # 遍历房子的链接
        for url in house_url_ls:
            item['houseURL'] = url
            self.house_detail(item)

    def run(self, city,folder_path):
        """获取所有城区的页面链接"""
        # 访问二手房网址
        self.driver.get(f'https://{city}.lianjia.com/ershoufang/')
        # 获取所有城区的元素对象
        temp_ls = self.driver.find_elements(By.XPATH, '//div[@class="position"]/dl[2]/dd/div[1]/div/a')
        # 城区名
        part_name_ls = [ele.text for ele in temp_ls]
        # 城区链接
        part_url_ls = [ele.get_attribute("href") for ele in temp_ls]
        item = {}  # 初始化一个容器, 用来存放房子的信息
        for i in range(len(temp_ls)):
            item['partName'] = part_name_ls[i]  # 城区名
            item['partURL'] = part_url_ls[i]  # 城区页面链接
            self.house_list(dict(item))  # 传递深拷贝的item对象

        pd.DataFrame(item).to_csv(folder_path+f'\{city}.csv', index=False, encoding='utf-8')
        self.driver.quit()

    
for city in cities:    
    # 创建目录
    folder_path = os.getcwd()+f"\data\房价\{city}"
    if not os.path.exists(folder_path):
        os.makedirs(folder_path)
    city1 = pinyin.get_initial(city).replace(" ", "")
    lj = LianJia()
    lj.run(city1,folder_path)