使用Beautiful Soup with Python

时间:2017-12-25 02:25:44

标签: python html web-scraping beautifulsoup

我正在尝试使用Beautiful Soup从booking.com获取一些酒店信息。我需要从西班牙的所有住宿中获取某些信息。这是搜索网址:

https://www.booking.com/searchresults.html?aid=304142&label=gen173nr-1DCAEoggJCAlhYSDNYBGigAYgBAZgBMbgBB8gBDNgBA-gBAfgBApICAXmoAgM&sid=1677838e3fc7c26577ea908d40ad5faf&class_interval=1&dest_id=197&dest_type=country&dtdisc=0&from_sf=1&group_adults=2&group_children=0&inac=0&index_postcard=0&label_click=undef&no_rooms=1&oos_flag=0&postcard=0&raw_dest_type=country&room1=A%2CA&sb_price_type=total&search_selected=1&src_elem=sb&ss=Spain&ss_all=0&ss_raw=spain&ssb=empty&sshis=0&order=popularity

当我使用开发人员工具检查结果页面中的住宿时,它说这是要搜索的标记:

<a class="hotel_name_link url" href="&#10;/hotel/es/aran-la-abuela.html?label=gen173nr-1DCAEoggJCAlhYSDNYBGigAYgBAZgBMbgBB8gBDNgBA-gBAfgBApICAXmoAgM;sid=1677838e3fc7c26577ea908d40ad5faf;ucfs=1;srpvid=b4980e34f6e50017;srepoch=1514167274;room1=A%2CA;hpos=1;hapos=1;dest_type=country;dest_id=197;srfid=198499756e07f93263596e1640823813c2ee4fe1X1;from=searchresults&#10;;highlight_room=#hotelTmpl" target="_blank" rel="noopener">
<span class="sr-hotel__name
" data-et-click="
customGoal:YPNdKNKNKZJUESUPTOdJDUFYQC:1
">
Hotel Spa Aran La Abuela
</span>
<span class="invisible_spoken">Opens in new window</span>
</a>

这是我的Python代码:

def init_BeautifulSoup():
    global page, soup
    page= requests.get("https://www.booking.com/searchresults.html?aid=304142&label=gen173nr-1DCAEoggJCAlhYSDNYBGigAYgBAZgBMbgBB8gBDNgBA-gBAfgBApICAXmoAgM&sid=1677838e3fc7c26577ea908d40ad5faf&class_interval=1&dest_id=197&dest_type=country&dtdisc=0&from_sf=1&group_adults=2&group_children=0&inac=0&index_postcard=0&label_click=undef&no_rooms=1&oos_flag=0&postcard=0&raw_dest_type=country&room1=A%2CA&sb_price_type=total&search_selected=1&src_elem=sb&ss=Spain&ss_all=0&ss_raw=spain&ssb=empty&sshis=0&order=popularity")
    soup = BeautifulSoup(page.content, 'html.parser')


def get_spain_accomodations():
    global accomodations
    accomodations = soup.find_all(class_="hotel_name_link.url")

但是当我运行代码并打印住宿变量时,它会输出一对括号([])。然后我打印了汤对象,我意识到解析的HTML与我在Chrome中的开发人员工具中看到的非常不同,这就是为什么汤对象无法找到类“hotel_name_link.url”

发生了什么事?

1 个答案:

答案 0 :(得分:2)

JavaScript正在加载后修改页面。因此,当您使用page.content时,它会在JavaScript修改页面之前为您提供页面的HTML内容。我不认为您可以直接使用requests模块来使用JavaScript抓取页面。 看看this问题。

如果您决定使用Selenium处理此问题,请检查this问题。页面加载后,您可以使用driver.page_souce在JavaScript修改后获取页面源并将其传递给BeautifulSoup。

from selenium import webdriver
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait

def get_page(url):
    driver = webdriver.Chrome()
    driver.get(url)
    try:
        WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, 'h1')))
    except TimeoutException:
        print('Page timed out.')
        return None
    page = driver.page_source
    return page

def init_BeautifulSoup():
    global page, soup
    page = get_page('your-url')
    # handle the case where page may be None
    soup = BeautifulSoup(page, 'html.parser')

不是快速或简单的解决方案,而是完成工作。

编辑:

你需要在这里改变一件事。

WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, 'h1')))部分的作用是让驱动程序明确等待,直到该元素位于我们指定的网页上,或者在您指定的延迟时间之后抛出TimeoutException(我是用了10秒)。

我刚给你提供了一个例子。您需要在执行JavaScript之前找到加载页面上不存在的元素,并在此处替换它:(By.TAG_NAME, 'h1')

您可以通过在加载页面后检查元素并在页面源的HTML代码中检查元素是否存在来执行此操作。

您可以根据您的要求使用以下任何内容代替By.TAG_NAME

  • ID
  • NAME
  • CLASS_NAME
  • CSS_SELECTOR
  • XPATH

我建议使用id或任何名称选择器而不是css或xpath,因为它们有点慢。 ID效果最快,而XPATH效果最慢。