Python 网页抓取-识别和执行请求;故障排除

Python 网页抓取-识别和执行请求;故障排除,python,web-scraping,python-requests,web-inspector,requests,Python,Web Scraping,Python Requests,Web Inspector,Requests,我在从以下网站抓取数据时遇到一些问题: 当我们加载页面时,它会加载圣保罗市real state的前30篇帖子。 如果我们向下滚动,它会加载更多的帖子 通常我会使用selenium来解决这个问题——但我想学习如何正确地完成它——我想这是通过处理请求实现的 通过在chrome上使用inspect,并观察向下滚动时发生的情况,我可以看到一个请求,我想这就是检索新帖子的原因 如果将其内容复制为curl,则会得到以下命令: curl "https://landscape-api.loft.co

我在从以下网站抓取数据时遇到一些问题:

当我们加载页面时,它会加载圣保罗市real state的前30篇帖子。 如果我们向下滚动,它会加载更多的帖子

通常我会使用selenium来解决这个问题——但我想学习如何正确地完成它——我想这是通过处理请求实现的

通过在chrome上使用inspect,并观察向下滚动时发生的情况,我可以看到一个请求,我想这就是检索新帖子的原因

如果将其内容复制为curl,则会得到以下命令:

curl "https://landscape-api.loft.com.br/listing/search?city=S^%^C3^%^A3o^%^20Paulo^&facetFilters^\[^\]=address.city^%^3AS^%^C3^%^A3o^%^20Paulo^&limit=18^&limitedColumns=true^&loftUserId=417b37df-19ab-4014-a800-688c5acc039d^&offset=28^&orderBy^\[^\]=rankB^&orderByStatus=^%^27FOR_SALE^%^27^%^2C^%^20^%^27JUST_LISTED^%^27^%^2C^%^20^%^27DEMOLITION^%^27^%^2C^%^20^%^27COMING_SOON^%^27^%^20^%^2C^%^20^%^27SOLD^%^27^&originType=LISTINGS_LOAD_MORE^&q=pin^&status^\[^\]=FOR_SALE^&status^\[^\]=JUST_LISTED^&status^\[^\]=DEMOLITION^&status^\[^\]=COMING_SOON^&status^\[^\]=SOLD" ^
  -X "OPTIONS" ^
  -H "Connection: keep-alive" ^
  -H "Accept: */*" ^
  -H "Access-Control-Request-Method: GET" ^
  -H "Access-Control-Request-Headers: loft_user_id,loftuserid,utm_campaign,utm_content,utm_created_at,utm_id,utm_medium,utm_source,utm_term,utm_user_agent,x-user-agent,x-utm-source,x-utm-user-id" ^
  -H "Origin: https://www.loft.com.br" ^
  -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36" ^
  -H "Sec-Fetch-Mode: cors" ^
  -H "Sec-Fetch-Site: same-site" ^
  -H "Sec-Fetch-Dest: empty" ^
  -H "Referer: https://www.loft.com.br/" ^
  -H "Accept-Language: en-US,en;q=0.9" ^
  --compressed
我不确定哪种方法是将其转换为python模块请求中使用的命令的正确方法,因此我使用了这个网站

结果是:

import requests

headers = {
    'Connection': 'keep-alive',
    'Accept': '*/*',
    'Access-Control-Request-Method': 'GET',
    'Access-Control-Request-Headers': 'loft_user_id,loftuserid,utm_campaign,utm_content,utm_created_at,utm_id,utm_medium,utm_source,utm_term,utm_user_agent,x-user-agent,x-utm-source,x-utm-user-id',
    'Origin': 'https://www.loft.com.br',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36',
    'Sec-Fetch-Mode': 'cors',
    'Sec-Fetch-Site': 'same-site',
    'Sec-Fetch-Dest': 'empty',
    'Referer': 'https://www.loft.com.br/',
    'Accept-Language': 'en-US,en;q=0.9',
}

params = (
    ('city', 'S\xE3o Paulo'),
    ('facetFilters/[/]', 'address.city:S\xE3o Paulo'),
    ('limit', '18'),
    ('limitedColumns', 'true'),
    ('loftUserId', '417b37df-19ab-4014-a800-688c5acc039d'),
    ('offset', '28'),
    ('orderBy/[/]', 'rankB'),
    ('orderByStatus', '\'FOR_SALE\', \'JUST_LISTED\', \'DEMOLITION\', \'COMING_SOON\' , \'SOLD\''),
    ('originType', 'LISTINGS_LOAD_MORE'),
    ('q', 'pin'),
    ('status/[/]', ['FOR_SALE', 'JUST_LISTED', 'DEMOLITION', 'COMING_SOON', 'SOLD']),
)

response = requests.options('https://landscape-api.loft.com.br/listing/search', headers=headers, params=params)
但是,当我尝试运行它时,会得到一个204

因此,我的问题是:

  • 识别本网站请求的正确/最佳方式是什么?有没有比我做的更好的选择
  • 一旦确定,复制为curl是复制命令的最佳方式吗
  • 如何在Python中最好地复制该命令
  • 为什么我会得到204分
  • 1-你做得很对!我已经用同样的方法做了很长一段时间了,根据我在网络垃圾处理方面的经验,使用
    你的浏览器网络选项卡
    是迄今为止获取网站请求信息的最佳方式,比我所知道的任何“扩展”和/或“插件”都要好!!!在
    kali-linux
    或windows上也有“打嗝服”,但浏览器上的“网络”选项卡始终是我的首选

    2-我一直在使用你提到的同一个网站!!!它让我的生活更轻松,工作也更顺畅。当然,你可以手动操作,但是你提到的网站让我更容易、更快,而且我已经用了很长时间了

    3-你可以手动完成,这很简单,但正如我所说,你提到的网站使它更容易和更快

    4-这可能是因为您正在使用
    请求。选项
    ,我会尝试使用
    请求。取而代之的是获取


    您查找请求的方法是正确的。但您需要找到并分析正确的请求。
    关于为什么得到204个响应代码而没有结果;您发送
    选项
    请求,而不是
    获取
    。在ChromeDevTools中,您可以看到两个类似的请求(查看附件图片)。一个是
    选项
    ,第二个是带类型的
    获取。
    对于网站,您需要第二个选项,但您在代码
    请求中使用了
    选项
    要查看请求的响应,请选择它并选中响应或预览选项卡

    Python中最好的HTTP库之一是

    下面是获取所有搜索结果的完整代码:

    import requests
    
    headers = {
        'x-user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_0) AppleWebKit/537.36 (KHTML, like Gecko) '
                        'Chrome/88.0.4324.146 Safari/537.36',
        'utm_created_at': '',
        'Accept': 'application/json, text/plain, */*',
    }
    
    with requests.Session() as s:
        s.headers = headers
    
        listings = list()
        limit = 18
        offset = 0
        while True:
            params = {
                "city": "São Paulo",
                "facetFilters/[/]": "address.city:São Paulo",
                "limit": limit,
                "limitedColumns": "true",
                # "loftUserId": "a2531ad4-cc3f-49b0-8828-e78fb489def8",
                "offset": offset,
                "orderBy/[/]": "rankA",
                "orderByStatus": "\'FOR_SALE\', \'JUST_LISTED\', \'DEMOLITION\', \'COMING_SOON\' , \'SOLD\'",
                "originType": "LISTINGS_LOAD_MORE",
                "q": "pin",
                "status/[/]": ["FOR_SALE", "JUST_LISTED", "DEMOLITION", "COMING_SOON", "SOLD"]
            }
            r = s.get('https://landscape-api.loft.com.br/listing/search', params=params)
            r.raise_for_status()
    
            data = r.json()
            listings.extend(data["listings"])
    
            offset += limit
            total = data["pagination"]["total"]
            if len(data["listings"]) == 0 or len(listings) == total:
                break
    
    print(len(listings))
    

    鲁维是对的。您需要从
    请求。选项
    更新到
    请求。获取
    。然后可以使用
    response.json()
    检索结果。