在 JavaScript 页面中使用 Python 请求
- 2025-01-06 08:32:00
- admin 原创
- 120
问题描述:
我正在尝试使用 Requests 框架和 python(http://docs.python-requests.org/en/latest/),但我尝试访问的页面使用 javascript 来获取我想要的信息。
我曾尝试在网上搜索解决方案,但事实上,我使用关键字 javascript 搜索时,得到的大部分内容都是如何使用 javascript 语言进行抓取。
有没有办法在使用 javascript 的页面中使用请求框架?
解决方案 1:
好消息:现在有一个支持 javascript 的请求模块: https://pypi.org/project/requests-html/
from requests_html import HTMLSession
session = HTMLSession()
r = session.get('http://www.yourjspage.com')
r.html.render() # this call executes the js in the page
我认为这是一个额外的收获BeautifulSoup
,所以你可以做类似的事情
r.html.find('#myElementID').text
它将按照您的期望返回 HTML 元素的内容。
解决方案 2:
您将必须发出与 javascript 相同的请求(使用 Requests 库)。您可以使用任意数量的工具(包括 Chrome 和 Firefox 内置的工具)来检查来自 javascript 的 http 请求,然后自己从 Python 发出此请求。
解决方案 3:
虽然 Selenium 看起来很诱人而且很有用,但它有一个无法解决的主要问题:性能。通过计算浏览器所做的每一件事,您将需要更多的功能。即使是 PhantomJS 也无法与简单的请求竞争。我建议您只在真正需要单击按钮时使用 Selenium。如果您只需要 javascript,我推荐 PyQt(查看https://www.youtube.com/watch?v=FSH77vnOGqU了解它)。
但是,如果您想使用 Selenium,我建议使用 Chrome 而不是 PhantomJS。许多用户在使用 PhantomJS 时遇到问题,网站在 Phantom 中根本无法运行。Chrome 也可以是无头的(非图形化的)!
首先,确保您已经安装了 ChromeDriver,Selenium 依赖于它来使用 Google Chrome。
然后,通过检查 URL chrome://settings/help 来确保您拥有 60 或更高版本的 Google Chrome
现在,您需要做的就是以下代码:
from selenium.webdriver.chrome.options import Options
from selenium import webdriver
chrome_options = Options()
chrome_options.add_argument("--headless")
driver = webdriver.Chrome(chrome_options=chrome_options)
如果您不知道如何使用 Selenium,这里有一个快速概述:
driver.get("https://www.google.com") #Browser goes to google.com
查找元素:使用 ELEMENTS 或 ELEMENT 方法。示例:
driver.find_element_by_css_selector("div.logo-subtext") #Find your country in Google. (singular)
driver.find_element(s)_by_css_selector(css_selector) # 与此 CSS 选择器匹配的每个元素
driver.find_element(s)_by_class_name(class_name) # 具有以下类的每个元素
driver.find_element(s)_by_id(id) # 具有以下 ID 的每个元素
driver.find_element(s)_by_link_text(link_text) # 每个带有完整链接文本
driver.find_element(s)_by_partial_link_text(partial_link_text) # 每个带有部分链接文本。
driver.find_element(s)_by_name(name) # 每个 name=argument 的元素
driver.find_element(s)_by_tag_name(tag_name) # 每个带有标签名称参数的元素
好的!我找到了一个元素(或元素列表)。但是我现在该做什么?
以下是可以在元素elem上执行的方法:
elem.tag_name # 可以返回按钮。
elem.get_attribute("id") # 返回元素的 ID。
elem.text # 元素的内部文本。
elem.clear() # 清除文本输入。
elem.is_displayed() # 可见元素为 True,不可见元素为 False。
elem.is_enabled() # 如果输入已启用,则为 True,否则为 False。
elem.is_selected() # 这个单选按钮或者复选框元素是否被选中了?
elem.location # 一个字典,表示屏幕上元素的 X 和 Y 位置。
elem.click() # 单击elem。
elem.send_keys("thelegend27") # 在elem中输入 thelegend27 (适用于文本输入)
elem.submit() # 提交elem参与的表单。
特殊命令:
driver.back() # 单击“返回”按钮。
driver.forward() # 单击“前进”按钮。
driver.refresh() # 刷新页面。
driver.quit() # 关闭浏览器(包括所有标签页)。
foo = driver.execute_script("return 'hello';") # 执行 javascript(可以获取返回值!)
解决方案 4:
使用 Selenium 或启用 jQuery 的请求很慢。更有效的方法是找出网站在浏览器上检查 JavaScript 后生成的 cookie,然后获取该 cookie 并将其用于每个请求。
在一个例子中,它通过以下 cookie 起作用:
本例中,检查 javascript 后生成的 cookie 是“cf_clearance”。因此只需创建一个会话。更新 cookie 和标头,如下所示:
s = requests.Session()
s.cookies["cf_clearance"] = "cb4c883efc59d0e990caf7508902591f4569e7bf-1617321078-0-150"
s.headers.update({
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.90 Safari/537.36"
})
s.get(url)
现在你不需要使用 Selenium 之类的 JavaScript 解决方案了。这种方式更快、更高效。你只需要在打开浏览器后获取一次 cookie 即可。
解决方案 5:
实现此目的的一种方法是使用 selenium 调用您的请求。让我们使用 pip 或 pip3 安装依赖项:
pip 安装硒
ETC。
如果您使用 python3 运行脚本,请改用:
pip3 安装硒
(...)
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager
driver = webdriver.Chrome(ChromeDriverManager().install())
url = 'http://myurl.com'
# Please wait until the page will be ready:
element = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.CSS_SELECTOR, "div.some_placeholder")))
element.text = 'Some text on the page :)' # <-- Here it is! I got what I wanted :)
解决方案 6:
也许有人会从我的经历中受益。对我来说,从 Pyaterochka 商店的网站收集信息是件很困难的事。第一页以 html 形式返回,但后续页面以 java 脚本形式返回。
from requests_html import HTMLSession
session = HTMLSession()
def fetch(url, params):
headers = params['headers']
return session.get(url, headers=headers)
current_page = 1
req = fetch(
f"https://5ka.ru/api/v2/special_offers/?records_per_page=15&page={current_page}&store=31Z6&ordering=&price_promo__gte=&price_promo__lte=&categories=&search=",
{
"headers": {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Gecko/20100101 Firefox/111.0",
"Accept": "application/json, text/plain, */*",
"Accept-Language": "ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3",
},
})
for pp in req.json()['results']:
print(f'
name = {pp["name"]}')
print(f'price = {pp["current_prices"]["price_promo__min"]}')
print(f'url = {pp["img_link"]}')
解决方案 7:
它是 pyppeteer 的包装器还是其他什么?:( 我以为它是其他东西
@property
async def browser(self):
if not hasattr(self, "_browser"):
self._browser = await pyppeteer.launch(ignoreHTTPSErrors=not(self.verify), headless=True, args=self.__browser_args)
return self._browser