如何使用 python 爬取全国小区名称

前言

笔者在做一个 N L P NLP NLP 项目时,需要识别小区名,因此想要查询网上是否有相关的数据集。经过一番搜索后一无所获…从而决定自己来爬取这份数据。

由于爬取网站的内容信息之后可能会发生变更,因此此处给出具体的爬虫思路,便于应对之后的网站结构变更。


方法

1. 爬取网站的确定

既然是爬虫,那首先就需要确定爬取网站。这时候就需要思考哪些网站可能会涉及小区名字?

  1. 国家统计网?经过一番搜索,没找到…
  2. 房屋中介网?

因此我们可以选取比较知名的房屋中介网来进行小区名爬取,此处选取的网站是链家,原因是该网站有专门的小区板块。链家
在这里插入图片描述

2. 网站结构分析

由于链家对于不同城市,建立了不同的网页,因此我们以北京的网页举例。

第一步,选中所有选项,查看当前网址。
https://bj.lianjia.com/xiaoqu/pg1y1y2y3y4y5p1p2p3p4p5p6/

多查看几个网页,就可以发现上述网址的共性,bj 是城市缩写,pg1 是页面编号。
在这里插入图片描述

第二步,查看当前网页的 H t m l Html Html,分析元素结构。

执行下述代码,即可查看该页面解析过后的格式。

from bs4 import BeautifulSoup
import requests

url = 'https://{}.lianjia.com/xiaoqu/pg{}y1y2y3y4y5p1p2p3p4p5p6/'
response = requests.get("https://bj.lianjia.com/xiaoqu/pg1y1y2y3y4y5p1p2p3p4p5p6/").text
soup = BeautifulSoup(response, 'lxml')
print(soup)

对上述输出的内容稍加搜索,即可发现小区名所在页面结构如下。可以发现在下面两种格式中均出现了小区名,一个在图片结构中,另一个是页面显示的文字,我们选取图片结构对小区信息进行提取。

<img alt="新龙城" class="lj-lazy" data-original="https://image1.ljcdn.com/hdic-resblock/025cb5ab-9460-417e-bd4b-78868900d752.jpg.232x174.jpg" src="https://s1.ljcdn.com/feroot/pc/asset/img/blank.gif?_v=20200331145335"/>

<a href="https://bj.lianjia.com/xiaoqu/1111027381003/" target="_blank">新龙城</a>

因此我们增加一行代码来提取 i m g img img 标签中的信息并输出。

text_list = soup.find_all('img', class_="lj-lazy")
for item in text_list:
    print(item['alt'])
# 输出结果:
# 首开康乃馨城
# 农光里
# 理想家园
# 华贸城
# 住欣家园
# 远洋山水
# 旗胜家园
# 小南庄社区
# ...
第三步,构造网站 u r l url url

首先我们考虑页面如何构造。这个难度不大,我们只需要 f o r for for 一遍页面编号即可。这个网站有一个特点在于,网站上可能只显示了 30 30 30 页,但是实际上可能有 100 100 100 页…并且假如第 100 100 100 页是最后一页,那么第 101 101 101 页的内容将与第 100 100 100 页保持一致。因此我们根据当前网页是否与上一个网页一致,来判断当前网站爬取是否结束。

def get_housing_estate():
    fo = open("data/housing_estate.txt", "w")
    # 设置初始值
    last = BeautifulSoup(requests.get(url.format("wz", 1)).text, 'lxml').find_all('img', class_="lj-lazy")
    for city in address_list:
        for page in range(1, 500):
            print(city, page)
            # 创建bs对象
            try:
                response = requests.get(url.format(city, page)).text
            except:
            	# 页面出错,则更换下一个城市
                break
            soup = BeautifulSoup(response, 'lxml')  # 使用到了lxml解析库
            text_list = soup.find_all('img', class_="lj-lazy")

            # 出现重复页面
            if text_list == last:
                break
            last = text_list

            # 写入文件
            for item in text_list:
                fo.write(item['alt'] + '\n')

接下来就要考虑城市简写如何爬取了。我们可以根据这个网站中提供的城市分类来对网站进行爬取。
在这里插入图片描述
然后问题就变成了这个网站的城市名如何爬取呢?流程与上述三步一致,爬取网页,分析结构,提取数据。此处就不再具体展开分析了,直接提供代码,大家也可以先不看代码,自己尝试爬取。

def get_address():
    response = requests.get("https://www.lianjia.com/city/").text
    soup = BeautifulSoup(response, 'lxml')

    text_list = soup.find_all('a')
    for item in text_list:
        if type(item.get('href')) == str and item.get('href')[0] == 'h':
            value = item.get('href').split("https://")[1].split('.')[0]
            if value not in address_list:
                address_list.append(value)
            if value == 'yw':
                break
    print(address_list)

3. 完整代码

在总代码中,笔者进行了两项处理。

  1. 使用 t r y − c a t c h try-catch trycatch 的方式保证页面 u r l url url 出错时,项目不会崩溃
  2. 通过记录前一个页面的方式,保证爬取页面时能及时退出
from bs4 import BeautifulSoup
import requests

address_list = []

url = 'https://{}.lianjia.com/xiaoqu/pg{}y1y2y3y4y5p1p2p3p4p5p6/'


def get_address():
    response = requests.get("https://www.lianjia.com/city/").text
    soup = BeautifulSoup(response, 'lxml')

    text_list = soup.find_all('a')
    for item in text_list:
        if type(item.get('href')) == str and item.get('href')[0] == 'h':
            value = item.get('href').split("https://")[1].split('.')[0]
            if value not in address_list:
                address_list.append(value)
            if value == 'yw':
                break
    print(address_list)


def get_housing_estate():
    fo = open("data/housing_estate.txt", "w")
    last = BeautifulSoup(requests.get(url.format("wz", 1)).text, 'lxml').find_all('img', class_="lj-lazy")
    for city in address_list:
        for page in range(1, 500):
            print(city, page)
            # 创建bs对象
            try:
                response = requests.get(url.format(city, page)).text
            except:
                break
            soup = BeautifulSoup(response, 'lxml')  # 使用到了lxml解析库
            text_list = soup.find_all('img', class_="lj-lazy")

            # 出现重复页面
            if text_list == last:
                break
            last = text_list

            # 写入文件
            for item in text_list:
                fo.write(item['alt'] + '\n')


def main():
    get_address()
    get_housing_estate()


if __name__ == "__main__":
    main()


后记

代码总体逻辑不难,总长度也不长,但可惜由于数据量太大,笔者爬了快 1 h 1h 1h 了也还没结束…使用者需有一定的耐心…
在这里插入图片描述
爬取过程仍在继续… (〃・o・〃)

### 使用Python编写爬虫程序从链家网获取全国小区数据 为了实现这一目标,可以从以下几个方面入手: #### 1. 数据采集 通过 `requests` 或 `scrapy` 库发送 HTTP 请求来访问链家网站并提取所需的信息。由于链家网站可能具有反爬机制,因此需要设置请求头(headers),模拟浏览器行为以降低被封禁的风险[^1]。 ```python import requests from bs4 import BeautifulSoup headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } def fetch_page(url): response = requests.get(url, headers=headers) if response.status_code == 200: return response.text else: raise Exception(f"Failed to load page {url}") ``` #### 2. 解析HTML文档 利用 `BeautifulSoup` 对 HTML 文档进行解析,定位到包含小区信息的标签节点,并从中抽取具体字段,例如小区名称、均价、物业费等[^2]。 ```python soup = BeautifulSoup(fetch_page('https://www.lianjia.com'), 'html.parser') communities = soup.find_all('div', class_='community-item') data = [] for community in communities: name = community.find('a').text.strip() price_per_square_meter = community.find('span', class_='price').text.strip() property_fee = community.find('span', class_='fee').text.strip() data.append({ 'name': name, 'price_per_square_meter': price_per_square_meter, 'property_fee': property_fee }) ``` #### 3. 存储数据至Excel文件 借助 `openpyxl` 模块创建一个新的工作簿对象并将抓取的数据逐行写入其中,最后保存为 `.xlsx` 文件格式以便后续分析处理[^3]。 ```python from openpyxl import Workbook wb = Workbook() ws = wb.active # 写表头 ws.append(['Name', 'Price Per Square Meter', 'Property Fee']) # 写数据 for item in data: ws.append([item['name'], item['price_per_square_meter'], item['property_fee']]) wb.save('lianjia_communities.xlsx') ``` 需要注意的是,在实际操作过程中可能会遇到诸如 IP 被封锁等问题,这时可以通过引入代理池或者适当延时等方式加以解决;另外考虑到法律风险以及道德规范等因素,在未经许可的情况下大规模爬取他人站点内容应谨慎行事[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Gene_INNOCENT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值