python爬虫获取链家二手房源信息

0X00 前言

本来之前是准备爬取boss直聘的招聘信息,结果boss的反爬还挺恶心,访问页面还得带上cookie,页面的cookie有效时间也只有一分钟,不然只能访问到等待页面,菜鸡落泪


0X01 准备工作

使用到的标准库lxml、requests、re、requests.exceptions、os和openpyxl、random、time。


0X02 分析

相比较boss来说,链家的网站对于爬虫友好得多,当然访问的时候还是得带上headers,不然也是会被识别出来是爬虫,从而被拒绝访问。

分析一下链家的url,举一个例子。https://cd.lianjia.com/ershoufang/pg1rs双流区/

他的子域名cd.lianjia.com中的cd就对应着成都市,想要访问其他城市的房源信息就可以通过修改它来达成。

后面路径中的pg1就对应着页数,可以通过修改它来达成翻页的效果。

而rs后面的信息就是我们搜索的内容。

很明显可以看出规律 https:// + city + .lianjia.com/ershoufang/pg +页码+ rs + 搜索内容/

url分析完了,来看看链家的页面:
在这里插入图片描述
在这里插入图片描述每一条租房信息都存在一个li标签中。

然后可能是因为他的设置原因,不管数据有再多,也只会显示100页出来,一页30条信息,一共就是3000条信息。

简单分析了一下,就下来就是代码实现。

0X03 代码实现

首先定义了两个全局变量count和total_count,用来记录爬取的页数和爬取的数据总数。

global count
global total_count

还用到了time库来记录程序运行时间。

start = time.time()	#开始时间
final = time.time()	#结束时间
print('爬取完毕,共花费' + str(final - start) + 's.')

这的话由于爬取的页数为100页,就直接写死了循环次数。

如果不确定页数有多少的话可以通过判断response的信息来判断是否为有效url,或者可以通过获取第一个页面下的总页数从而得知总页数的数量,这偷了个懒。

为了防止访问过于频繁从而导致ip被ban,可以使用sleep将程序挂起几秒,避免访问过于频繁。

for i in range(1, 101):
    url = 'https://cd.lianjia.com/ershoufang/pg' + str(i) + 'rs双流区/'
    time.sleep(random.randint(0, 3))
    main(url)

然后是简单的main函数。

通过get_one_page函数得到页面的返回信息,如果返回不为None,就调用
parse_page函数来解析数据,然后存入表格中。

def main(url):
    html_data = get_one_page(url)
    if html_data is not None:
        parse_page(html_data)

为了防止被ban,多准备几个User-Agent,然后访问的时候随机从里面取一个出来放入headers。

def get_one_page(url):
    try:
        ua = [
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0",
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1",
            "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)",
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
            "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.9.168 Version/11.50",
            "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.0)"
        ]
        headers = {"User-Agent": random.choice(ua)}
        response = requests.get(url=url, headers=headers)
        if response.status_code == 200:
            return response.text
        else:
            return None
    except RequestException:
        return None

然后就通过xpath来获取页面中我们想要的信息。

不过感觉这样显得好笨重,不知道有没有更简单的方法,害

data_text = etree.HTML(html_data)
description = data_text.xpath('//*[@id="content"]/div[1]/ul/li/div[1]/div[1]/a/text()')
address = data_text.xpath('//*[@id="content"]/div[1]/ul/li/div[1]/div[2]/div/a[1]/text()')
specific_situation = data_text.xpath('//*[@id="content"]/div[1]/ul/li/div[1]/div[3]/div/text()')
total_price = data_text.xpath('//*[@id="content"]/div[1]/ul/li/div[1]/div[6]/div[1]/span/text()')
unit_price = data_text.xpath('//*[@id="content"]/div[1]/ul/li/div[1]/div[6]/div[2]/span/text()')
attention = data_text.xpath('//*[@id="content"]/div[1]/ul/li/div[1]/div[4]/text()')

然后通过操作xlsx文件,将我们获得的信息全部存入文件当中。

0X04 完整代码

import os
import random
import time

import openpyxl
import requests

from requests.exceptions import RequestException
from lxml import etree
import re


def get_one_page(url):
    try:
        ua = [
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0",
            "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1",
            "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)",
            "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36",
            "Opera/9.80 (Windows NT 6.1; U; zh-cn) Presto/2.9.168 Version/11.50",
            "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; GTB7.0)"
        ]
        headers = {"User-Agent": random.choice(ua)}
        response = requests.get(url=url, headers=headers)
        if response.status_code == 200:
            return response.text
        else:
            return None
    except RequestException:
        return None


def parse_page(html_data):
    data_text = etree.HTML(html_data)
    description = data_text.xpath('//*[@id="content"]/div[1]/ul/li/div[1]/div[1]/a/text()')
    address = data_text.xpath('//*[@id="content"]/div[1]/ul/li/div[1]/div[2]/div/a[1]/text()')
    specific_situation = data_text.xpath('//*[@id="content"]/div[1]/ul/li/div[1]/div[3]/div/text()')
    total_price = data_text.xpath('//*[@id="content"]/div[1]/ul/li/div[1]/div[6]/div[1]/span/text()')
    unit_price = data_text.xpath('//*[@id="content"]/div[1]/ul/li/div[1]/div[6]/div[2]/span/text()')
    attention = data_text.xpath('//*[@id="content"]/div[1]/ul/li/div[1]/div[4]/text()')
    # 打开文件
    file_name = '成都市双流区二手房源.xlsx'
    global total_count
    # 判断文件是否存在
    if os.path.exists(file_name):
        wb = openpyxl.load_workbook(file_name)
        print(file_name + '打开成功!')
        ws = wb.active
    else:
        wb = openpyxl.Workbook()  # 创建文件对象
        print('文件' + file_name + '创建成功!')
        ws = wb.active
        ws.append(['房源描述', '地址', '房源情况', '规格', '面积', '总价(万)', '单价(元/平米)', '信息发布情况'])
    for i in range(0, len(description)):
        price = re.search('单价(\\d*?)元/平米', unit_price[i], flags=0)
        list = specific_situation[i].split(' | ')
        specification = list[0]
        area = re.search('(.*)平米', list[1], flags=0).group(1)
        ws.append(
            [description[i], address[i], specific_situation[i], specification, area, total_price[i], price.group(1),
             attention[i]])
        total_count += 1
    global count
    count += 1
    print('第' + str(count) + '页爬取成功!')
    wb.save(filename=file_name)


def main(url):
    html_data = get_one_page(url)
    if html_data is not None:
        parse_page(html_data)


if __name__ == '__main__':
    global count
    global total_count
    count = 0
    total_count = 0
    start = time.time()
    for i in range(1, 101):
        url = 'https://cd.lianjia.com/ershoufang/pg' + str(i) + 'rs双流区/'
        time.sleep(random.randint(0, 3))
        main(url)
    final = time.time()
    print('爬取完毕,共花费' + str(final - start) + 's.')
    print('共爬取' + str(count) + '页数据')
    print('共爬取' + str(total_count) + '条数据')

0X05 成果图

在这里插入图片描述

下次应该会学一学python的数据分析来分析分析爬取到的数据?应该吧,应该不会鸽吧,害。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值