Python多线程爬取链家房源,保存表格,实现数据可视化分析!

使用Python来爬取二手房源数据,并保存表格,实现数据分析!

软件环境

Python 3.8

Pycharm

代码展示

模块

# 数据请求模块 --> 第三方模块, 需要安装 pip install requests
import requests
# 解析数据模块 --> 第三方模块, 需要安装 pip install parsel
import parsel
# csv模块
import csv

 

创建文件

f = open('data.csv', mode='w', encoding='utf-8', newline='')
csv_writer = csv.DictWriter(f, fieldnames=[
    '标题',
    '小区',
    '区域',
    '售价',
    '单价',
    '户型',
    '面积',
    '朝向',
    '装修',
    '楼层',
    '年份',
    '建筑类型',
    '详情页',
])
csv_writer.writeheader()

 

发送请求, 模拟浏览器 对于 url地址 发送请求

模拟浏览器

headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}

 

请求网址/网站

url = 'https://cs.lianjia.com/ershoufang/'

# 完整源码,视频讲解直接+这个扣裙:279199867 免费领取

 

发送请求

response = requests.get(url=url, headers=headers)
# <Response [200]> 响应对象 200 状态码 表示请求成功
print(response)

 

获取数据, 获取网页源代码 <获取服务器返回响应数据>

解析数据, 提取我们想要的数据内容

解析方法:

  • re: 对于字符串数据直接进行解析提取

  • css: 根据标签属性提取数据内容

  • xpath: 根据标签节点提取数据内容

使用css: 根据标签属性提取数据内容

把获取到html字符串数据, 转成可解析对象

selector = parsel.Selector(response.text)

 

获取所有房源信息所在li标签

lis = selector.css('.sellListContent li.clear')

 

for循环遍历

for li in lis:
    """
提取具体房源信息: 标题 / 价格 / 位置 / 户型... .title a --> 表示定位class类名为title下面a标签 """ title = li.css('.title a::text').get() # 标题 info_list = li.css('.positionInfo a::text').getall() area = info_list[0] # 小区名字 area_1 = info_list[1] # 地区 totalPrice = li.css('.totalPrice span::text').get() # 售价 unitPrice = li.css('.unitPrice span::text').get().replace('元/平', '').replace(',', '') # 单价 houseInfo = li.css('.houseInfo::text').get().split(' | ') # 信息 houseType = houseInfo[0] # 户型 houseArea = houseInfo[1].replace('平米', '') # 面积 houseFace = houseInfo[2] # 朝向 fitment = houseInfo[3] # 装修 fool = houseInfo[4] # 楼层 if len(houseInfo) == 7 and '' in houseInfo[5]: year = houseInfo[5].replace('年建', '') else: year = '' house = houseInfo[-1] # 建筑类型 href = li.css('.title a::attr(href)').get() # 详情页 dit = { '标题': title, '小区': area, '区域': area_1, '售价': totalPrice, '单价': unitPrice, '户型': houseType, '面积': houseArea, '朝向': houseFace, '装修': fitment, '楼层': fool, '年份': year, '建筑类型': house, '详情页': href, } csv_writer.writerow(dit) print(dit) # print(title, area, area_1, totalPrice, unitPrice, houseType, houseArea, houseFace, fitment, fool, year, house, href)

 

多线程

导入模块

import requests
import parsel
import re
import csv
# 线程池模块
import concurrent.futures
import time

 

发送请求函数

def get_response(html_url):

:param html_url:
:return:
"""
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
}
response = requests.get(url=html_url, headers=headers)
return response

 

获取数据函数

def get_content(html_url):
    """
    :param html_url:
    :return:
    """
    response = get_response(html_url)
    html_data = get_response(link).text
    selector = parsel.Selector(response.text)
    select = parsel.Selector(html_data)
    lis = selector.css('.sellListContent li')
    content_list = []
    for li in lis:

        title = li.css('.title a::text').get()  # 标题
        area = '-'.join(li.css('.positionInfo a::text').getall())  # 小区
        Price = li.css('.totalPrice span::text').get()  # 总价
        Price_1 = li.css('.unitPrice span::text').get().replace('元/平', '')  # 单价
        houseInfo = li.css('.houseInfo::text').get()  # 信息
        HouseType = houseInfo.split(' | ')[0]  # 户型
        HouseArea = houseInfo.split(' | ')[1].replace('平米', '')  # 面积
        direction = houseInfo.split(' | ')[2].replace(' ', '')  # 朝向
        renovation = houseInfo.split(' | ')[3]  # 装修
        floor_info = houseInfo.split(' | ')[4]
        floor = floor_info[:3]  # 楼层
        floor_num = re.findall('(\d+)层', floor_info)[0]  # 层数
        BuildingType = houseInfo.split(' | ')[-1]
        string = select.css('.comments div:nth-child(7) .comment_text::text').get()
        href = li.css('.title a::attr(href)').get()  # 详情页
        if len(houseInfo.split(' | ')) == 6:
            date = 'None'
        else:
            date = houseInfo.split(' | ')[5].replace('年建', '')  # 日期
        print(string)
        dit = {
            '标题': title,
            '内容': string,
            '小区': area,
            '总价': Price,
            '单价': Price_1,
            '户型': HouseType,
            '面积': HouseArea,
            '朝向': direction,
            '装修': renovation,
            '楼层': floor,
            '层数': floor_num,
            '建筑日期': date,
            '建筑类型': BuildingType,
            '详情页': href,
        }
        content_list.append(dit)
    return content_list

 

主函数

def main(page):
    """
    :param page:
    :return:
    """
    print(f'===============正在采集第{page}页的数据内容===============')
    url = f'https:///ershoufang/yuelu/p{page}/'
    content_list = get_content(html_url=url)
    for content in content_list:
        csv_writer.writerow(content)


if __name__ == '__main__':
    time_1 = time.time()
    link = 'http://******/article/149'
    # 创建文件
    f = open('data多线程.csv', mode='a', encoding='utf-8', newline='')
    csv_writer = csv.DictWriter(f, fieldnames=[
        '标题',
        '内容',
        '小区',
        '总价',
        '单价',
        '户型',
        '面积',
        '朝向',
        '装修',
        '楼层',
        '层数',
        '建筑日期',
        '建筑类型',
        '详情页',
    ])
    csv_writer.writeheader()

    # 线程池执行器 max_workers 最大线程数
    exe = concurrent.futures.ThreadPoolExecutor(max_workers=10)
    for page in range(1, 11):
        exe.submit(main, page)
    exe.shutdown()
    time_2 = time.time()
    use_time = int(time_2 - time_1)
    # 总计耗时: 9
    print('总计耗时:', use_time)

 

热门相关:超武穿梭   法医王妃不好当!   最强装逼打脸系统   惊世毒妃:轻狂大小姐   修仙界最后的单纯