用Python抓取Airbnb列出数据

评论: 0

获得Airbnb数据的访问对于分析房地产市场,研究租赁价格动态,进行竞争性分析以及评估评论和评级至关重要。这可以通过刮擦Web数据来完成。但是,访问这些数据可能会具有挑战性,因为刮擦可能违反了网站的使用条款。

接下来,我们将探讨如何使用Python和Selenium从Airbnb列表中提取数据的逐步指南。本指南还将涵盖如何避免平台施加的潜在块和限制。

了解Airbnb网站的架构

创建网络刮板的第一步是了解如何访问您感兴趣的网页,因为网站的结构经常会改变。为了熟悉站点的结构,您可以使用浏览器的开发人员工具来检查网页的HTML。

要访问开发人员工具,请右键单击网页上,然后选择“检查”或使用快捷方式:

  • CTRL+SHIFT+I 对于Windows;
  • Option + ⌘ + I 在Mac上.

每个列表容器都包裹在DIV元素中,并具有以下属性:class =“ g1qv1ctd”。

1.png

通过单击“位置”并键入“英国伦敦”,我们可以访问伦敦提供的位置。该网站建议添加登记入住日期和退房日期。它使他们可以计算房间的价格。

2.png

此页面的URL看起来像这样:

url = "https://www.airbnb.com/s/London--United-Kingdom/homes?tab_id=home_tab&refinement_paths%5B%5D=%2Fhomes&flexible_trip_lengths%5B%5D=one_week&monthly_start_date=2024-01-01&monthly_length=3&price_filter_input_type=0&channel=EXPLORE&query=London%2C%20United%20Kingdom&place_id=ChIJdd4hrwug2EcRmSrV3Vo6llI&date_picker_type=calendar&source=structured_search_input_header&search_type=autocomplete_click"

从搜索页面中,我们将删除产品列表数据的以下属性:

  • 列表URL;
  • 标题;
  • 描述;
  • 等级;
  • 价格;
  • 其他清单信息(没有床和可用日期)。

3.png

构建Airbnb刮擦程序的分步指南

要开始使用Airbnb数据的网络刮擦,您需要首先设置开发环境。这是这样做的步骤:

步骤1:创建虚拟环境

虚拟环境使您可以隔离Python软件包及其对不同项目的依赖项。这有助于防止冲突并确保每个项目都安装了正确的依赖关系。

在Windows上创建虚拟环境

打开具有管理员特权的命令提示符,并运行以下命令,以创建一个名为“ VENV”的新虚拟环境:

python -m venv venv

激活虚拟环境:

venv\Scripts\activate

在MacOS/Linux上创建虚拟环境

打开终端并运行以下命令,创建一个名为“ VENV”的新虚拟环境:

sudo python3 -m venv venv

激活虚拟环境:

source venv/bin/activate

要停用虚拟环境,只需运行以下命令:

deactivate

步骤2:安装所需库

现在您已经设置了虚拟环境,可以安装必要的库。

了解库:

  • Selenium:这种功能强大的Web刮擦工具使您可以编程控制Web浏览器。这使您可以与网页进行交互,包括单击按钮,填充表格和浏览页面,就像您是真正的用户一样。
  • Seleniumwire:该库通过允许您拦截和检查HTTP请求并将代理与您的刮擦操作集成在一起,从而扩展了Selenium。这非常重要,因为硒没有本地代理支持。
  • BeautifulSoup4:这是一个旨在解析HTML和XML文件的库。它可以帮助您以结构化有效的方式从网页中提取特定信息。
  • LXML:一个快速,强大的HTML和XML解析器,可以补充美丽的套件。

在激活的虚拟环境中,运行以下命令以安装所需的库:

pip install selenium beautifulsoup4 lxml seleniumwire

硒司机

硒要求驱动器与所选浏览器接口。我们将使用Chrome进行本指南。但是,请确保您已为您选择的浏览器安装了适当的WebDriver。

下载后,确保将驱动程序放置在系统路径环境变量可访问的目录中。这将使硒可以找到驱动器并控制浏览器。

步骤3:导入库

在Python文件的开头,导入Seleniumwire和美丽的库库。这就是您的方式:

from seleniumwire import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
import time
import csv
import random

我们还将为各种公用事业导入`random',``时间''和`CSV库。

步骤4:代理集成

接下来,我们定义一个代理列表,以避免被Airbnb阻塞。在尝试无需溢价代理的请求时,您可能会遇到“访问拒绝”响应。

4.png

您可以设置代理如下:

# 代理列表
proxies = [
     "username:password@Your_proxy_IP_Address:Your_proxy_port1",
     "username:password@Your_proxy_IP_Address:Your_proxy_port2",
     "username:password@Your_proxy_IP_Address:Your_proxy_port3",
     "username:password@Your_proxy_IP_Address:Your_proxy_port4",
     "username:password@Your_proxy_IP_Address:Your_proxy_port5",

]

确保用您从代理人获得的实际代理地址替换“ your_proxy_ip_address”和“ your_proxy_port”,并用实际的凭据替换“用户名”和“密码”的值。

步骤5:旋转代理

旋转代理是网络刮擦的关键方面。网站从同一IP地址收到多个请求时,通常会阻止或限制对机器人和刮板的访问。通过旋转不同的代理IP地址,您可以避免检测,以多个有机用户的形式出现,并绕过网站上实施的大多数反搭化措施。

要设置代理旋转,请导入“随机”库。我们还定义一个函数`get_proxy()`从我们的列表中选择一个代理。此函数使用Random.Choice()方法从代理列表中随机选择代理,然后返回所选代理。

def get_proxy():
    return random.choice(proxies)

步骤6:设置WebDriver

接下来,我们定义称为`listings()`的主要函数。在这里,我们将在这里设置“ Chromedriver”。此功能使用Selenium来浏览属性清单页面,等待页面加载,并使用美丽的汤来解析HTML。

def listings(url):

    proxy = get_proxy()
    proxy_options = {
        "proxy": {
            "http": f"http://{proxy}",
            "https": f"http://{proxy}",
            "no_proxy": "localhost,127.0.0.1",
        }
    }

    chrome_options = Options()
    chrome_options.add_argument("--headless")
  

    s = Service(
        "C:/Path_To_Your_WebDriver"
    )  # 取代您的Chromedriver的道路
    driver = webdriver.Chrome(
        service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
    )

    driver.get(url)

    time.sleep(8)  # Adjust based on website's load time

    soup = BeautifulSoup(driver.page_source, "lxml")

    driver.quit()

在这里,我们首先选择一个随机代理并设置代理选项。这些选项将用于配置WebDriver以使用代理服务器。接下来,我们设置了Chrome选项。添加 - 无头参数以在无头模式下运行浏览器,这意味着浏览器将在没有图形用户界面的情况下运行。

然后使用服务,Seleniumwire选项和Chrome选项初始化WebDriver。然后使用WebDriver导航到给定的URL。我们增加了8秒的睡眠时间,以使页面完全加载,然后使用美丽的汤来解析返回的HTML。解析完成后,它将关闭网络驱动器。

步骤7:查找和提取清单数据

成功获得HTML内容后,下一步就是为每个清单提取相关数据。使用BeautifulSoup,我们可以轻松地浏览HTML结构并找到包含清单信息的元素。

提取清单元素

首先,我们确定页面上的所有清单元素。这些元素包含我们感兴趣的数据,例如列表URL,标题,描述,评级,价格和其他信息。

listing_elements = soup.find_all("div", class_="g1qv1ctd")
for listing_element in listing_elements:

该代码使用BeautifulSoup的Find_all()方法来定位使用“ G1QV1CTD”类的所有分数元素。这些元素代表Airbnb页面上的单个列表。然后,它循环遍历这些清单元素以提取相关数据。

提取清单URL

对于找到的每个清单元素,我们提取列表的URL。

URL_element = soup.find("a", class_="rfexzly")
listing_data["Listing URL"] = (
    "https://www.airbnb.com" + URL_element["href"] if URL_element else ""
)

在这里,我们在“汤”对象中搜索带有“ rfexzly”类的锚标签。如果找到此元素,它将提取“ HREF”属性(包含相对URL)并将其附加到基本URL以创建完整的列表URL。如果找不到元素,它将分配一个空字符串以避免错误。

提取清单标题

首先,我们将提取每个清单的URL。如果需要,这将使我们稍后访问单独的列表页面。

title_element = listing_element.find("div", class_="t1jojoys")
listing_data["Title"] = (
    title_element.get_text(strip=True) if title_element else ""
)

标题包含在“ Div”元素中,其中包括“ T1Jojoys”。我们检索此元素的文本内容,剥夺任何领先或尾随的空格。如果找不到元素,则存储一个空字符串。

提取清单描述

Description_element = listing_element.find("span", class_="t6mzqp7")
listing_data["Description"] = (
    Description_element.get_text(strip=True) if Description_element else ""
)

与标题提取类似,此代码在类“ T6MZQP7”类中找到一个跨度元素。然后,我们提取并清洁此元素的文本内容,其中包含清单的简短描述。

提取清单等级

rating_element = listing_element.find("span", class_="ru0q88m")
listing_data["Rating"] = (
    rating_element.get_text(strip=True) if rating_element else ""
)

如上面的代码所示,具有“ RU0Q88M”类的跨度元素具有评级值。我们提取此值,以确保剥离任何不必要的空格。

提取上市价格

最后,我们提取清单的价格。

price_element = listing_element.select_one("._1y74zjx")
listing_data["Price"] = (
    f"{price_element.get_text(strip=True)} per night" if price_element else ""
)

此代码在当前listing_element中使用类“ _1Y74ZJX”类定位元素。如果找到通常包含价格信息的元素,则将其文本内容提取,清洁和附加“每晚”,以形成一个更有用的价格字符串。

提取其他清单信息

有些列表可能有我们可以提取的其他信息。

listing_info_element = listing_element.find("span", {"aria-hidden": "true"})
listing_data["Additional Listing information"] = (
    listing_info_element.get_text(strip=True) if listing_info_element else ""
)

我们搜索具有属性aria-hidden =“ true”的跨度元素,以找到有关清单的任何其他信息。从每个清单元素中提取所有相关数据后,我们将收集的数据附加到列表列表中。

listings.append(listing_data)

处理所有列表后,我们返回列表列表,每个列表称为包含提取数据的字典。

return listings

步骤8:将数据写入CSV文件

在成功刮取Airbnb清单页面的数据之后,下一个重要的步骤是存储这些有价值的信息,以供将来分析和参考。我们将CSV库用于此任务。我们在写入模式下打开一个CSV文件,并创建一个csv.dictwriter对象。然后,我们将标题和数据写入文件。

airbnb_listings = listings(url)

csv_file_path = "proxy_web_listings_output.csv"

with open(csv_file_path, "w", encoding="utf-8", newline="") as csv_file:
    fieldnames = [
        "Listing URL",
        "Title",
        "Description",
        "Rating",
        "Price",
        "Additional Listing information",
    ]
    writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
    writer.writeheader()
    for listing in airbnb_listings:
        writer.writerow(listing)

print(f"Data has been exported to {csv_file_path}")

这是我们用于本教程的完整代码:

from seleniumwire import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
import time
import csv
import random

# 代理列表
proxies = [ 
 "username:password@Your_proxy_IP_Address:Your_proxy_port1",
 "username:password@Your_proxy_IP_Address:Your_proxy_port2",
 "username:password@Your_proxy_IP_Address:Your_proxy_port3",
 "username:password@Your_proxy_IP_Address:Your_proxy_port4",
 "username:password@Your_proxy_IP_Address:Your_proxy_port5",
]

def get_proxy():
    return random.choice(proxies)


def listings(url):

    proxy = get_proxy()
    proxy_options = {
        "proxy": {
            "http": f"http://{proxy}",
            "https": f"http://{proxy}",
            "no_proxy": "localhost,127.0.0.1",
        }
    }

    chrome_options = Options()
    chrome_options.add_argument("--headless")
  

    s = Service(
        "C:/Path_To_Your_WebDriver"
    )  # 取代您的Chromedriver的道路
    driver = webdriver.Chrome(
        service=s, seleniumwire_options=proxy_options, chrome_options=chrome_options
    )

    driver.get(url)

    time.sleep(8)  # 根据网站的加载时间进行调整

    soup = BeautifulSoup(driver.page_source, "lxml")

    driver.quit()

    listings = []

    # 在页面上查找所有清单元素
    listing_elements = soup.find_all("div", class_="g1qv1ctd")

    for listing_element in listing_elements:
        # 从每个清单元素中提取数据
        listing_data = {}

        # 列表URL
        URL_element = soup.find("a", class_="rfexzly")
        listing_data["Listing URL"] = (
            "https://www.airbnb.com" + URL_element["href"] if URL_element else ""
        )

        # 标题
        title_element = listing_element.find("div", class_="t1jojoys")
        listing_data["Title"] = (
            title_element.get_text(strip=True) if title_element else ""
        )

        # 描述
        Description_element = listing_element.find("span", class_="t6mzqp7")
        listing_data["Description"] = (
            Description_element.get_text(strip=True) if Description_element else ""
        )

        # 等级
        rating_element = listing_element.find("span", class_="ru0q88m")
        listing_data["Rating"] = (
            rating_element.get_text(strip=True) if rating_element else ""
        )

        # 价格
        price_element = listing_element.select_one("._1y74zjx")
        listing_data["Price"] = (
            f"{price_element.get_text(strip=True)} per night" if price_element else ""
        )

        # 其他清单信息
        listing_info_element = listing_element.find("span", {"aria-hidden": "true"})
        listing_data["Additional Listing information"] = (
            listing_info_element.get_text(strip=True) if listing_info_element else ""
        )

        # 将清单数据附加到列表
        listings.append(listing_data)

    return listings


url = "https://www.airbnb.com/s/London--United-Kingdom/homes?tab_id=home_tab&refinement_paths%5B%5D=%2Fhomes&flexible_trip_lengths%5B%5D=one_week&monthly_start_date=2024-01-01&monthly_length=3&price_filter_input_type=0&channel=EXPLORE&query=London%2C%20United%20Kingdom&place_id=ChIJdd4hrwug2EcRmSrV3Vo6llI&date_picker_type=calendar&source=structured_search_input_header&search_type=autocomplete_click"


airbnb_listings = listings(url)

csv_file_path = "proxy_web_listings_output.csv"

with open(csv_file_path, "w", encoding="utf-8", newline="") as csv_file:
    fieldnames = [
        "Listing URL",
        "Title",
        "Description",
        "Rating",
        "Price",
        "Additional Listing information",
    ]
    writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
    writer.writeheader()
    for listing in airbnb_listings:
        writer.writerow(listing)

print(f"Data has been exported to {csv_file_path}")

代码的这一部分确保刮擦数据存储在名为“ Proxy_web_listings_output.csv”的CSV文件中。

结果

如下所示,我们的刮板结果保存到称为“ Proxy_web_listings_output.csv”的CSV文件中。

5.jpg

本指南有效地说明了如何使用Python从Airbnb列表中刮擦数据,从而提取了关键细节,例如价格,可用性和评论。它强调了使用代理并旋转它们以防止Airbnb的反机器人措施阻止的重要性。

评论:

0 评论