''' requests:用于发起HTTP请求,获取网页数据,是网络爬虫和API调用的常用库。 BeautifulSoup:与requests库配合使用,用于解析获取的网页内容,提取所需的信息。 pandas:提供了大量易用的数据处理功能,如数据清洗、转换、分析等,特别适合处理结构化数据。 time:提供了各种与时间相关的操作,例如等待(sleep)功能,可以用来控制程序的执行节奏,或作为简单的定时器。 ''' # 导入requests库,这是一个简单易用的HTTP库,用于发送请求获取网页内容 import requests # 导入BeautifulSoup库,它是一个用于解析HTML和XML文档的库,常用于网页数据抓取 from bs4 import BeautifulSoup # 导入pandas库,这是一个数据分析和操作库,常用于处理表格数据,如Excel、CSV文件等 import pandas as pd # 导入time库,这个库包含了时间相关的函数,如暂停执行(time.sleep)等 import time ''' get_html函数的主要作用是向指定的URL发送HTTP GET请求,并获取响应的HTML内容。 通过设置headers,我们模拟了浏览器的用户代理信息,这有助于避免一些网站对爬虫的反爬措施。 response.raise_for_status()会检查响应状态码,如果状态码指示请求失败(例如404或500),它将抛出一个异常。 如果请求成功,函数将返回响应的文本内容,通常是一个HTML文档的字符串形式。 ''' def get_html(url): """ 发送HTTP GET请求获取指定URL的HTML内容。 参数: - url: 请求的网址字符串 返回: - 请求得到的HTML内容 """ # 定义请求头headers,模拟浏览器访问 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' } # 发送GET请求,获取网页内容 response = requests.get(url, headers=headers) # raise_for_status()方法会在请求失败时抛出异常 response.raise_for_status() # 返回请求得到的HTML内容 return response.text ''' parse_html函数的主要作用是解析传入的HTML内容,并提取具有特定类名的元素中的文本信息。 它使用了BeautifulSoup库,这是Python中一个非常流行的用于解析HTML和XML文档的库。 函数通过查找具有特定class属性的HTML标签,并提取它们的文本内容,构建了一个包含这些信息的列表。 如果某个标签不存在,函数会使用字符串'N/A'作为占位符。最后,函数返回这个列表,其中每个元素都是一个包含提取字段的列表。 ''' def parse_html(html): """ 解析HTML内容,提取特定结构的数据。 参数: - html: HTML文档的字符串形式 返回: - data: 包含提取数据的列表,每个元素是一个列表,包含单个数据项的字段 """ # 使用BeautifulSoup解析HTML,'html.parser'是Python标准库的解析器 soup = BeautifulSoup(html, 'html.parser') # 初始化一个空列表,用于存储解析出来的数据 data = [] # 寻找所有class为'content__list--item--main'的div标签 for item in soup.find_all('div', class_='content__list--item--main'): # 在当前item中寻找class为'content__list--item--title twoline'的p标签 rent_type_tag = item.find('p', class_='content__list--item--title twoline') # 在当前item中寻找class为'content__list--item--des'的p标签 location_tag = item.find('p', class_='content__list--item--des') # 在当前item中寻找class为'content__list--item--area'的span标签 area_tag = item.find('span', class_='content__list--item--area') # 在当前item中寻找class为'content__list--item--direction'的span标签 direction_tag = item.find('span', class_='content__list--item--direction') # 在当前item中寻找class为'content__list--item-price'的span标签 price_tag = item.find('span', class_='content__list--item-price') # 提取文本内容,并去除首尾空白字符;如果标签不存在,则使用'N/A' rent_type = rent_type_tag.text.strip() if rent_type_tag else 'N/A' # 去除文本中的换行符和多余空格;如果标签不存在,则使用'N/A' location = location_tag.text.strip().replace('\n', '').replace(' ', '') if location_tag else 'N/A' area = area_tag.text.strip() if area_tag else 'N/A' direction = direction_tag.text.strip() if direction_tag else 'N/A' price = price_tag.text.strip() if price_tag else 'N/A' # 将提取的数据作为一个列表元素添加到data列表中 data.append([rent_type, location, area, direction, price]) # 返回包含所有数据的列表 return data ''' save_to_csv函数的主要作用是将传入的数据(data)转换为pandas的DataFrame对象,并将其保存到CSV文件中。 DataFrame是pandas中用于存储表格数据的主要数据结构,非常适合进行数据清洗、转换、分析等操作。 函数中使用了pd.DataFrame()构造函数来创建DataFrame对象,其中data参数是要保存的数据,可以是列表的列表、列表的字典或其他可迭代对象。 columns参数指定了DataFrame的列名。 接着,使用to_csv()方法将DataFrame对象保存到CSV文件中。to_csv()方法有几个重要的参数: filename: 要写入的CSV文件的名称。 index: 如果设置为False,在保存CSV文件时不包含DataFrame的索引。 encoding: 指定文件的编码格式,这里使用'utf-8-sig',它是一种带BOM(字节顺序标记)的UTF-8编码,有助于确保CSV文件在不同的编辑器中正常打开和显示。 ''' def save_to_csv(data, filename): """ 将数据保存到CSV文件。 参数: - data: 要保存的数据,通常是一个列表的列表或字典的列表 - filename: 要保存到的CSV文件名 """ # 将数据转换为pandas DataFrame对象,指定列名为['Rent Type', 'Location', 'Area', 'Direction', 'Price'] df = pd.DataFrame(data, columns=['Rent Type', 'Location', 'Area', 'Direction', 'Price']) # 将DataFrame对象df保存到CSV文件,filename指定文件名 # index=False参数表示在保存时不包含行索引 # encoding='utf-8-sig'指定文件编码为UTF-8带BOM格式,这有助于确保文件在不同的编辑器中正常显示 df.to_csv(filename, index=False, encoding='utf-8-sig') ''' main 函数的主要作用是从一个房产租赁网站的特定城市页面抓取租房数据。 它使用了之前定义的 get_html、parse_html 和 save_to_csv 函数来获取网页内容、解析数据和保存数据。 函数中使用了 while 循环来连续获取多页数据,直到没有更多数据或发生错误为止。 在请求过程中,使用 try-except 结构来捕获并处理可能出现的异常,以确保程序的健壮性。 ''' def main(city_code): """ 主函数,用于从指定城市的链家网站抓取租房数据并保存到CSV文件。 参数: - city_code: 城市代码,用于构造请求的URL """ base_url = f'https://{city_code}.lianjia.com/zufang/pg{{}}' # 定义基础URL模板,用于后续拼接具体页面的URL all_data = [] # 初始化一个空列表,用于存储所有抓取的数据 page = 1 # 初始化页面计数器为1 # 使用while循环不断请求下一页,直到没有数据或发生错误 while True: url = base_url.format(page) # 使用当前页码格式化URL print(f'Fetching page {page}...') # 打印正在获取的页面信息 try: html = get_html(url) # 获取当前页面的HTML内容 data = parse_html(html) # 解析HTML内容并提取数据 if not data: # 如果没有数据,跳出循环 break all_data.extend(data) # 将当前页的数据添加到总数据列表中 page += 1 # 页码加1,准备获取下一页 # time.sleep(1) # 避免过于频繁的请求导致被封,注释掉表示不使用 except requests.RequestException as e: # 捕获requests库可能抛出的请求异常 print(f'Error fetching page {page}: {e}') # 打印错误信息 break # 发生异常,跳出循环 # 将所有抓取的数据保存到CSV文件中 save_to_csv(all_data, f'{city_code}zuf.csv') print(f'Saved data to {city_code}zuf.csv') # 打印保存成功的消息 # 这是一个特殊的条件判断行,用于判断当前脚本是否作为主程序运行 # 如果是主程序(而不是被其他脚本导入),则执行以下代码块 if __name__ == '__main__': # 调用main函数,传入字符串'bj'作为参数 # 这里假设'bj'是某个特定城市的城市代码,用于获取该城市的租房数据 main('bj') # 'bj' for Beijing, replace with other city codes as needed ''' 详细解释: __name__ 是一个内置变量,用于存储当前脚本的名称。 当Python脚本被直接运行时,__name__ 的值会被设置为 '__main__'。 如果脚本是被另一个脚本导入的,__name__ 的值将被设置为脚本文件的名称(不包含.py扩展名)。 条件 if __name__ == '__main__': 用于检查当前脚本是否作为独立程序运行。如果是,将执行该条件块内的代码。 在这个条件块中,调用了 main 函数,并传入 'bj' 作为参数。 这里的 'bj' 通常代表北京的城市代码,意味着 main 函数将执行获取北京租房数据的逻辑。 使用这种模式的好处是,即使脚本被其他Python脚本导入,也不会自动执行 main 函数内的代码,从而避免不必要的执行和潜在的副作用。 只有当你直接运行这个脚本时,main 函数才会被调用。这是一种良好的编程实践,有助于提高代码的模块化和可重用性。 '''
lianjia 0.01
最新推荐文章于 2025-05-20 18:44:14 发布