【问题标题】:Scraping JSON from AJAX calls从 AJAX 调用中抓取 JSON
【发布时间】:2020-04-16 15:11:28
【问题描述】:

背景

考虑到这个网址:

base_url = "https://www.olx.bg/ad/sobstvenik-tristaen-kamenitsa-1-CID368-ID81i3H.html"

我想对电话号码进行 ajax 调用:

ajax_url = "https://www.olx.bg/ajax/misc/contact/phone/7XarI/?pt=e3375d9a134f05bbef9e4ad4f2f6d2f3ad704a55f7955c8e3193a1acde6ca02197caf76ffb56977ce61976790a940332147d11808f5f8d9271015c318a9ae729"

想要的结果

如果我在控制台中的 chrome 浏览器中通过网站按下按钮,我会得到想要的结果

{"value":"088 *****"}

调试

如果我打开一个新标签并粘贴 ajax_url,我总是会得到空值:

{"value":"000 000 000"}

如果我尝试类似:

重击:

wget $ajax_url

Python:

import requests


json_response= requests.get(ajax_url)

我只会收到网站处理页面的 html 有错误。

想法

当我使用浏览器打开请求时,我还有更多内容。我还有什么?也许是饼干?

如何使用 Bash/Python 获得想要的结果?

编辑

响应html的代码是200

我尝试过使用 curl,但遇到了同样的 html 问题。

某种修复。

我注意到,如果我复制浏览器的 cookie,并使用包含来自浏览器的 cookie 的所有标头发出请求,我会得到正确的结果

# I think the most important header is the cookie
headers = DICT_WITH_HEADERS_FROM_BROWSER
json_response= requests.get(next_url,
                            headers=headers,
                            )

最后一个问题

剩下的唯一问题是如何通过 Python 脚本生成 cookie?

【问题讨论】:

  • 您是否看过 curl 或 Postman,Chrome 插件?这个链接也可以帮助realpython.com/python-json
  • @JGFMK Curl 给了我同样的错误 html 错误,而不是想要的 JSON 输出。我检查了你发给我的链接。如果你有 JSON,它有很好的信息,我的问题是我无法得到 JSON。我现在会检查其余的
  • 嗯,这是什么错误?
  • @Iguananaut 我将进行编辑而不是返回 JSON 结构,它会返回站点处理程序的 html,以处理错误、有问题的请求
  • “它会返回站点处理程序的 html,以处理错误的、有问题的请求”,您已经说过了。 exact 错误是什么?还应该有一个数字 HTTP 错误代码。这些东西很有意义。

标签: python json ajax networking web-scraping


【解决方案1】:

首先您应该创建一个请求会话来存储 cookie。 然后向实际调用 ajax 请求的页面发送一个 http GET 请求。如果网站创建了任何 cookie,它会在 GET 响应中发送,并且您的会话会存储 cookie。 然后就可以很方便的使用session调用ajax api了。

重要提示1: 您在原网站调用的ajax url 是http POST 请求!您不应该向该网址发送获取请求。

重要提示2: 您还必须从网站 js 代码中提取 phoneToken,该代码存储在 var phoneToken = 'here is the pt'; 等变量中

示例代码:

import re
import requests

my_session = requests.Session()

# call html website
base_url = "https://www.olx.bg/ad/sobstvenik-tristaen-kamenitsa-1-CID368-ID81i3H.html"
base_response = my_session.get(url=base_url)
assert base_response.status_code == 200

# extract phone token from base url response
phone_token = re.findall(r'phoneToken\s=\s\'(.+)\';', base_response.text)[0]

# call ajax api
ajax_path = "/ajax/misc/contact/phone/81i3H/?pt=" + phone_token
ajax_url = "https://www.olx.bg" + ajax_path
ajax_headers = {
    'accept': '*/*',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'en-US,en;q=0.9,fa;q=0.8',
    'sec-fetch-mode': 'cors',
    'sec-fetch-site': 'same-origin',
    'Referer': 'https://www.olx.bg/ad/sobstvenik-tristaen-kamenitsa-1-CID368-ID81i3H.html',
    'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36'
}
ajax_response = my_session.post(url=ajax_url, headers=ajax_headers)

print(ajax_response.text)

当你运行上面的代码时,会显示下面的结果:

{"value":"088 558 9937"}

【讨论】:

  • 你得到什么输出,我得到了有问题的 {"value":"000 000 000"} ,我在没有设置 cookie 时收到。
  • @Harton 这个答案是完全无效的,以防您在寻找更多信息。让我知道,这样我就可以编辑我的答案并发表解释
  • @Harton 检查我的更新答案。现在代码会自动从网站中提取 phoneToken 并打印正确的结果。将 selenium 与 webdriver 一起使用是可行的,但它没有用,并且对于这样一个简单的网络抓取需要大量资源。
  • @SinaRezaei 现在它的作品,我删除了我的反对票并赞成它。
【解决方案2】:
from selenium import webdriver
from bs4 import BeautifulSoup
from selenium.webdriver.firefox.options import Options
from bs4 import BeautifulSoup
import time

options = Options()
options.add_argument('--headless')

driver = webdriver.Firefox(options=options)
driver.get(
    'https://www.olx.bg/ad/sobstvenik-tristaen-kamenitsa-1-CID368-ID81i3H.html')

number = driver.find_element_by_xpath(
    "/html/body/div[3]/section/div[3]/div/div[1]/div[2]/div/ul[1]/li[2]/div/strong").click()
time.sleep(2)
source = driver.page_source
soup = BeautifulSoup(source, 'html.parser')

phone = soup.find("strong", {'class': 'xx-large'}).text

print(phone)

输出:

088 558 9937

【讨论】:

  • 看起来不错,但我收到了selenium.common.exceptions.WebDriverException: Message: connection refused
  • @Harton 你能通过浏览器浏览网站吗?如果是,请删除以下 options = Options()options.add_argument('--headless')options=options 并重新运行脚本并让我知道结果。
  • 也让我知道你的OS类型
  • 使用 linux,ping 失败,我想我必须解决访问权限以及 cookie 问题
  • @Harton 在我看来,由于您的多次请求,您被阻止了。
猜你喜欢
  • 2017-05-14
  • 2014-04-08
  • 1970-01-01
  • 2015-12-13
  • 2016-10-09
  • 2023-04-04
  • 2012-07-12
相关资源
最近更新 更多