如何用Python从airbnb上的多个url中抓取数据



我设法从AirBnB的登录页(价格、名称、评级等)中抓取所有数据,我还知道如何使用循环来使用分页来从多个页面中抓取数据。

我想做的是为每个特定的列表抓取数据,即列表页面中的数据(描述、便利设施等)。

我想的是实现与分页相同的逻辑,因为我有一个带链接的list,但我很难理解如何做到这一点。

以下是刮取链接的代码:

进口

from bs4 import BeautifulSoup
from selenium import webdriver
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
import pandas as pd
import time

获取页面

airbnb_url = 'https://www.airbnb.com/s/Thessaloniki--Greece/homes?tab_id=home_tab&flexible_trip_lengths%5B%5D=one_week&refinement_paths%5B%5D=%2Fhomes&place_id=ChIJ7eAoFPQ4qBQRqXTVuBXnugk&query=Thessaloniki%2C%20Greece&date_picker_type=calendar&search_type=unknown'
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
driver.get(airbnb_url)
driver.maximize_window()
time.sleep(5)

报废链接

links = []
soup=BeautifulSoup(driver.page_source, 'lxml')
for card in soup.select('div[class="c4mnd7m dir dir-ltr"]'):
links.append('https://www.airbnb.com' + card.select_one('a[class="ln2bl2p dir dir-ltr"]')['href'])

我过去提取的";在哪里睡觉";部分是这个,但可能我用错了标签。

amenities = []
for url in links:
driver.get(url)
soup1 = BeautifulSoup(driver.page_source, 'lxml')
for amenity in soup1.select('div[class="t2pjd0h dir dir-ltr"]'):
amenities.append(amenity.select_one('div[class="_1r21qb98"]'))

我的第一个问题是,另一个问题是如果没有人,我如何才能获得每个列表的可用性。

非常感谢!

BeautifulSoup在某些情况下更舒适,但并非在您的抓取过程中所需的所有方面-还应避免通过动态类选择元素,使用time并切换到selenium waits

在所有列表页面上迭代时,我建议使用while-loop来保持脚本的通用性,并在每次迭代中检查是否有下一个可用页面,否则使用break作为循环。这消除了手动计数页面和条目以及使用静态range()的需要。

try:
next_page = WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'[data-section-id="EXPLORE_NUMBERED_PAGINATION:TAB_ALL_HOMES"] button + a'))).get_attribute('href')
except:
next_page = None
#### process your data
if next_page:
airbnb_url = next_page
else:
break

要刮去所有的便利设施,你必须通过点击按钮打开模式:

[i.text.split('n')[0] for i in WebDriverWait(driver, 5).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,'[data-testid="modal-container"] [id$="-row-title"]')))] 

注意:为了避免其他元素点击时出现错误,请检查您是否必须处理cookie横幅

要提取卧室信息,请检查更多静态信息,如id或HTML结构,并检查元素是否可用-这行提取了本节中的所有信息,并从标题和值创建了一个dict

if soup.select_one('[data-section-id="SLEEPING_ARRANGEMENT_DEFAULT"] div+div'):
sleep_areas = list(soup.select_one('[data-section-id="SLEEPING_ARRANGEMENT_DEFAULT"] div+div').stripped_strings)
d.update(dict(zip(sleep_areas[0::2], sleep_areas[1::2])))
else:
d.update({'Bedroom':None})

示例

只是为了指明一个方向,并不是每个人都必须进行完全抓取,我在本例中将对象的抓取限制为每页urls[:1],只需删除[:1]即可获得所有结果。

import pandas as pd
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
options = webdriver.ChromeOptions()
options.add_argument("--lang=en")
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()),options=options)
airbnb_url = 'https://www.airbnb.com/s/Thessaloniki--Greece/homes?tab_id=home_tab&flexible_trip_lengths%5B%5D=one_week&refinement_paths%5B%5D=%2Fhomes&place_id=ChIJ7eAoFPQ4qBQRqXTVuBXnugk&query=Thessaloniki%2C%20Greece&date_picker_type=calendar&search_type=unknown'
driver.maximize_window()

data = []
while True:
driver.get(airbnb_url)
urls = list(set(a.get_attribute('href') for a in WebDriverWait(driver, 5).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,'[itemprop="itemListElement"] a')))))
try:
next_page = WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'[data-section-id="EXPLORE_NUMBERED_PAGINATION:TAB_ALL_HOMES"] button + a'))).get_attribute('href')
except:
next_page = None
print('Scrape listings from page:' + str(next_page))
for url in urls[:1]:
driver.get(url)
WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.CSS_SELECTOR,'[data-section-id="AMENITIES_DEFAULT"] button'))).click()
soup = BeautifulSoup(driver.page_source)
d = {
'title':soup.h1.text,
'amenities':[i.text.split('n')[0] for i in WebDriverWait(driver, 5).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR,'[data-testid="modal-container"] [id$="-row-title"]')))]
}
if soup.select_one('[data-section-id="SLEEPING_ARRANGEMENT_DEFAULT"] div+div'):
sleep_areas = list(soup.select_one('[data-section-id="SLEEPING_ARRANGEMENT_DEFAULT"] div+div').stripped_strings)
d.update(dict(zip(sleep_areas[0::2], sleep_areas[1::2])))
else:
d.update({'Bedroom':None})
data.append(d)
if next_page:
airbnb_url = next_page
else:
break
pd.DataFrame(data)

输出

>公共空间tbody>
title便利设施
08 NETFLIX BELGIUM HELLEXPO UNIVERSITY['','洗发水','必需品','衣架','熨斗','电视','空调','暖气','烟雾报警器','一氧化碳报警器','Wifi','专用工作区','烹饪基础','允许长期停留','不可用:物业上的安全摄像头','无法使用:厨房','不能使用:洗衣机','只能使用:私人入口']1张沙发床nannan
4ASOPOOSTUDIO["吹风机"、"洗发水"、"热水"、"必需品"、"、"床单"、"熨斗"、"电视"、"暖气"、"无线网络"、"厨房"、"冰箱"、"餐具和银器"、"免费街道停车场"、"电梯"、"带薪场外停车"、"允许长期入住"、"主人问候您"、"不可用:洗衣机"、《不可用:空调》、《不可使用:烟雾报警器》、《无法使用:一氧化碳报警器》、e: 私人入口']1张沙发床一张双人床
14Aristotelous 8楼1层,视野开阔["热水"、"沐浴露"、"免费洗衣机-单元内"、"必需品"、"衣架"、"床单"、"熨斗"、"衣物烘干架"、"服装储藏室"、"电视"、"打包/旅行婴儿床-可根据要求提供"、"空调"、"暖气"、"无线网络"、"专用工作区"、"厨房"、"冰箱"、"微波炉"、"烹饪基础"、"餐具和银器"、"炉灶"、"热水壶"、"咖啡机","烤床单"、"咖啡"、"餐桌"、"私人露台或阳台"、"户外家具"、"带薪停车场"、"允许携带宠物"、"可以放行李"、"长期住宿"、"自助入住"、"锁箱"、"不可用:酒店内的安全摄像头"、"无法使用:烟雾报警器"、"不能使用:一氧化碳报警器",'不可用:私人入口']nan

您想在每个详细信息页面的同时刮取总的列表页面。因此,每页包含20个总项目编号,也就是20个偏移项目,这意味着每页的偏移量每次增加20个列出的项目。我已经通过以下偏移量在起始url中进行了分页,然后第二次进入细节页面调用驱动程序和汤,从细节页面中,您必须提取所有必要的信息。

共有15个页面,单个页面有20个列表项目,因此总列表为15*20=300个列表。我刮了6页,意思是120个项目,意思是(0120,20)。你可以提取所有(0300,20)项目,只需将它们注入范围函数中。首先,测试我的代码,因为selenium有点慢,所以它会消耗更多的时间。

脚本:

from bs4 import BeautifulSoup
from selenium import webdriver
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
import pandas as pd
import time
url = 'https://www.airbnb.com/s/Thessaloniki--Greece/homes?tab_id=home_tab&flexible_trip_lengths%5B%5D=one_week&refinement_paths%5B%5D=%2Fhomes&place_id=ChIJ7eAoFPQ4qBQRqXTVuBXnugk&query=Thessaloniki%2C%20Greece&date_picker_type=calendar&search_type=user_map_move&price_filter_input_type=0&ne_lat=40.66256734970964&ne_lng=23.003752862853986&sw_lat=40.59051931897441&sw_lng=22.892087137145978&zoom=13&search_by_map=true&federated_search_session_id=1ed21e1c-0c5e-4529-ab84-267361eac02b&pagination_search=true&items_offset={offset}&section_offset=2'
data = []
for offset in range(0,120,20):
driver.get(url.format(offset=offset))
driver.maximize_window()
time.sleep(3)
soup=BeautifulSoup(driver.page_source, 'lxml')

detailed_pages = []
for card in soup.select('div[class="c4mnd7m dir dir-ltr"]'):
link = 'https://www.airbnb.com' + card.select_one('a[class="ln2bl2p dir dir-ltr"]').get('href')
detailed_pages.append(link)

for page in detailed_pages:
driver.get(page)
driver.maximize_window()
time.sleep(2)
soup2=BeautifulSoup(driver.page_source, 'lxml')
price = soup2.select_one('span._tyxjp1')
price = price.text if price else None
rating= soup2.select_one('span._12si43g')
rating = rating.text if rating else None
Bedroom_area = soup2.select_one('div[class="_1a5glfg"]')
Bedroom_area = Bedroom_area.text if Bedroom_area else None
place_offers= ', '.join([x.get_text(strip=True) for x in soup2.select('[class="sewcpu6 dir dir-ltr"]+div:nth-of-type(3) > div')])
data.append({
'place_offers': place_offers,
'price':price,
'rating':rating,
'Bedroom_area': Bedroom_area
})
df=pd.DataFrame(data)
print(df)

输出:

place_offers                                     price   rating             Bedroom_area
0                                                        $23    None                     None
1                                                        $39  4.75 ·                     None
2                                                        $65   5.0 ·                     None
3    Kitchen, Wifi, TV, Washer, Air conditioning, P...   $90  4.92 ·                     None
4    Wifi, TV, Air conditioning, Hair dryer, Paid p...   $18  4.67 ·                     None
..                                                 ...   ...     ...                      ...
115  Kitchen, Wifi, Free street parking, Pets allow...   $43  4.83 ·  1 queen bed, 1 sofa bed
116  Kitchen, Wifi, HDTV with Netflix, Elevator, Ai...   $38  4.73 ·             1 double bed
117  Wifi, Dedicated workspace, TV, Elevator, AC - ...   $34  4.85 ·                     None
118  City skyline view, Kitchen, Wifi, Dedicated wo...   $47  4.81 ·                     None
119  Kitchen, Wifi, Free street parking, TV with Ne...   $38  4.88 ·                     None
[120 rows x 4 columns]

最新更新