使用Requests / BeautifulSoup抓取网站时绕过脚本响应

时间:2017-02-23 02:50:28

标签: javascript python web-scraping beautifulsoup python-requests

我正在抓www.marriot.com获取有关其酒店和价格的信息。我使用chrome检查工具来监控网络流量,以确定哪个API端点marriot正在使用。

这是我试图模仿的请求:

http://www.marriott.com/reservation/availabilitySearch.mi?propertyCode=TYSMC&isSearch=true&fromDate=02/23/17&toDate=02/24/17&numberOfRooms=1&numberOfGuests=1&numberOfChildren=0&numberOfAdults=1

使用我的python代码:

import requests
from bs4 import BeautifulSoup

base_uri = 'https://www.marriott.com'
availability_search_ext = '/reservation/availabilitySearch.mi'

rate_params = {
   'propertyCode': 'TYSMC',
   'isSearch': 'true',
   'fromDate': '03/01/17',
   'toDate': '03/02/17',
   'numberOfRooms': '1',
   'numberOfGuests': '1',
   'numberOfChildren': '0',
   'numberOfAdults': '1'
}

def get_rates(sess):
    first_resp = sess.get(base_uri + availability_search_ext, params=rate_params)
    soup = BeautifulSoup(first_resp.content, 'html.parser')
    print soup.title

if __name__ == "__main__":
    with requests.Session() as sess:
        #get_hotels(sess)
        get_rates(sess)

然而,我得到了这个结果:

<!DOCTYPE doctype html>

<html>
<head><script src="/common/js/marriottCommon.js" type="text/javascript"> </script>
<meta charset="utf-8">
</meta></head>
<body>
<script>
        var xhttp = new XMLHttpRequest();
        xhttp.addEventListener("load", function(a,b,c){
          window.location.reload()
        });
        xhttp.open('GET', '/reservation/availabilitySearch.mi?istl_enable=true&istl_data', true);
        xhttp.send();
      </script>
</body>
</html>

他们似乎正试图阻止僵尸程序抓取他们的数据,以便他们发回一个重新加载页面的脚本,发送XHR请求,然后点击此端点http://www.marriott.com/reservation/rateListMenu.mi来渲染网页。

所以我尝试通过将我的python代码更改为此函数来模拟返回的javascript的行为:

rate_list_ext = '/reservation/rateListMenu.mi'    
xhr_params = {
    'istl_enable': 'true',
    'istl_data': ''
}

def get_rates(sess):
    first_resp = sess.get(base_uri + availability_search_ext,
                          params=rate_params)
    rate_xhr_resp = sess.get(base_uri + availability_search_ext,
                             params=xhr_params)
    rate_list_resp = sess.get(base_uri + rate_list_ext)
    soup = BeautifulSoup(rate_list_resp.content, 'html.parser')

我正在使用所有参数创建初始get请求,然后我发出脚本正在进行的xhr请求,然后我向rateListMenu.mi端点发出请求以尝试获取最终的html页面但是我得到了会话超时响应。

我甚至与请求库建立了持久会话,以便在阅读后存储网站返回的任何Cookie:Different web site response with RoboBrowser

我做错了什么?

1 个答案:

答案 0 :(得分:0)

当javascript发出get请求时,它包含标题。如果您包含大量这些标头,则您的请求应获得类似的返回值。

示例:

headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.100 Safari/537.36"}

sess.get(base_uri + availability_search_ext, params=rate_params, headers=headers)