- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
每当我想在 amazon.com 上抓取时,我都会失败。因为产品信息会根据 amazon.com 中的位置而变化
这个变化信息如下;
用selenium改变位置很简单,但是处理速度很慢。所以这就是为什么我需要使用 scrapy 或 requests 进行抓取。
但是,虽然我在浏览器中模仿 cookie 和 header ,但 amazon.com 不允许我更改位置。
有两个大问题。
有趣的是,没有关于这个主题的信息。你不能对世界排名第一的购物网站进行面向位置的抓取。
请知道这个话题答案的人赐教。如果有scrapy或者requests这样的解决方案就足够了。说真的,我已经有 1 年没有解决这个问题了。
import requests
from lxml import etree
from random import choice
from urllib3.exceptions import InsecureRequestWarning
import urllib.parse
import urllib3.request
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def location():
headersdelivery = {
'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36',
'content-type':'application/x-www-form-urlencoded',
'accept':'text/html,*/*',
'x-requested-with':'XMLHttpRequest',
'contenttype':'application/x-www-form-urlencoded;charset=utf-8',
'origin':'https://www.amazon.com',
'sec-fetch-site':'same-origin',
'sec-fetch-mode':'cors',
'sec-fetch-dest':'empty',
'referer':'https://www.amazon.com/',
'accept-encoding':'gzip, deflate, br',
'accept-language':'tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7'
}
payload = {
'locationType':'LOCATION_INPUT',
'zipCode':'34249',
'storeContext':'generic',
'deviceType':'web',
'pageType':'Gateway',
'actionSource':'glow',
'almBrandId':'undefined'}
sessionid = requests.session()
url = "https://www.amazon.com/gp/delivery/ajax/address-change.html"
ulkesecmereq = sessionid.post(url, headers=headersdelivery, data=payload,verify=False)
return sessionid
def response(locationsession):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.190 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en-US,en;q=0.5',
'Accept-Encoding': 'gzip, deflate, br',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'TE': 'Trailers'}
postdata = {
'storeContext':'generic',
'pageType':'Gateway'
}
req = locationsession.post("https://www.amazon.com/gp/glow/get-location-label.html",headers=headers, data=postdata, verify=False)
print(req.content)
locationsession = location()
response(locationsession)
最佳答案
首先,您应该从亚马逊基础页面获取 token anti-csrftoken-a2z
:
使用特定的用户代理向 www.amazon.com
发出请求:Mozilla ...
通过 XPATH 选择器获取 JSON 数据:
//span[@id='nav-global-location-data-modal-action']/@data-a-modal
来自此选择器的 JSON 示例:
{
"width": 375,
"closeButton": "false",
"popoverLabel": "Choose your location",
"ajaxHeaders": {
"anti-csrftoken-a2z": "ajaxHeaders >> anti-csrftoken-a2z"
},
"name": "glow-modal",
"url": "/gp/glow/get-address-selections.html?deviceType=desktop&pageType=Gateway&storeContext=NoStoreName&actionSource=desktop-modal",
"footer": "<span class=\"a-declarative\" data-action=\"a-popover-close\" data-a-popover-close=\"{}\"><span class=\"a-button a-button-primary\"><span class=\"a-button-inner\"><button name=\"glowDoneButton\" class=\"a-button-text\" type=\"button\">Done</button></span></span></span>",
"header": "Choose your location"
}
headers = {
"anti-csrftoken-a2z": `gMDCYRgjYFVWvjfmU70/qMURqYh7kAko11WlenYAAAAMAAAAAGGokFZyYXcAAAAA`,
"user-agent": "Mozila ..."
}
向链接发出请求:https://www.amazon.com/gp/glow/get-address-selections.html?deviceType=desktop&pageType=Gateway&storeContext=NoStoreName&actionSource=desktop-modal带有来自第 2 步的 header 和来自第 1 步的响应 cookie。
从响应中提取 CSRF_TOKEN
:正则表达式:'CSRF_TOKEN : "(.+?)"'
为下一个请求制作 header :
headers = {
"anti-csrftoken-a2z": "CSRF token from step 4",
"user-agent": "Mozila ..."
}
https://www.amazon.com/gp/delivery/ajax/address-change.html
使用表单数据:{
"locationType": "LOCATION_INPUT",
"zipCode": "zip-code",
"storeContext": "generic",
"deviceType": "web",
"pageType": "Gateway",
"actionSource": "glow",
"almBrandId": "undefined",
}
带有来自第 5 步的 header 和来自第 3 步的响应 cookie。
如果所有文件都应该得到这样的响应:
{
'isValidAddress': 1,
'isTransitOutOfAis': 0,
'address': {'locationType': 'LOCATION_INPUT', 'district': None,
'zipCode': '30322', 'addressId': None, 'isDefaultShippingAddress': 'false', 'obfuscatedId': None, 'isAccountAddress': 'false', 'state': 'GA',
'countryCode': 'US', 'addressLabel': None,
'city': 'ATLANTA', 'addressLine1': None}, 'sembuUpdated': 1
}
包含所有逻辑的 Python 脚本:
import json
import requests
from parsel import Selector
AMAZON_US_URL = "https://www.amazon.com/"
AMAZON_ADDRESS_CHANGE_URL = (
"https://www.amazon.com/gp/delivery/ajax/address-change.html"
)
AMAZON_CSRF_TOKEN_URL = (
"https://www.amazon.com/gp/glow/get-address-selections.html?deviceType=desktop"
"&pageType=Gateway&storeContext=NoStoreName&actionSource=desktop-modal"
)
DEFAULT_USER_AGENT = (
"Mozilla/5.0 ..."
)
DEFAULT_REQUEST_HEADERS = {"Accept-Language": "en", "User-Agent": DEFAULT_USER_AGENT}
def get_amazon_content(start_url: str, cookies: dict = None) -> tuple:
response = requests.get(
url=start_url, headers=DEFAULT_REQUEST_HEADERS, cookies=cookies
)
response.raise_for_status()
return Selector(text=response.text), response.cookies
def get_ajax_token(content: Selector):
data = content.xpath(
"//span[@id='nav-global-location-data-modal-action']/@data-a-modal"
).get()
if not data:
raise ValueError("Invalid page content")
json_data = json.loads(data)
return json_data["ajaxHeaders"]["anti-csrftoken-a2z"]
def get_session_id(content: Selector):
session_id = content.re_first(r'session: \{id: "(.+?)"')
if not session_id:
raise ValueError("Session id not found")
return session_id
def get_token(content: Selector):
csrf_token = content.re_first(r'CSRF_TOKEN : "(.+?)"')
if not csrf_token:
raise ValueError("CSRF token not found")
return csrf_token
def send_change_location_request(zip_code: str, headers: dict, cookies: dict):
response = requests.post(
url=AMAZON_ADDRESS_CHANGE_URL,
data={
"locationType": "LOCATION_INPUT",
"zipCode": zip_code,
"storeContext": "generic",
"deviceType": "web",
"pageType": "Gateway",
"actionSource": "glow",
"almBrandId": "undefined",
},
headers=headers,
cookies=cookies,
)
assert response.json()["isValidAddress"], "Invalid change response"
return response.cookies
def get_session_cookies(zip_code: str):
response = requests.get(url=AMAZON_US_URL, headers=DEFAULT_REQUEST_HEADERS)
content = Selector(text=response.text)
headers = {
"anti-csrftoken-a2z": get_ajax_token(content=content),
"user-agent": DEFAULT_USER_AGENT,
}
response = requests.get(
url=AMAZON_CSRF_TOKEN_URL, headers=headers, cookies=response.cookies
)
content = Selector(text=response.text)
headers = {
"anti-csrftoken-a2z": get_token(content=content),
"user-agent": DEFAULT_USER_AGENT,
}
send_change_location_request(
zip_code=zip_code, headers=headers, cookies=dict(response.cookies)
)
# Verify that location changed correctly.
response = requests.get(
url=AMAZON_US_URL, headers=DEFAULT_REQUEST_HEADERS, cookies=response.cookies
)
content = Selector(text=response.text)
location_label = content.css("span#glow-ingress-line2::text").get().strip()
assert zip_code in location_label
if __name__ == "__main__":
get_session_cookies(zip_code="30322")
另外,使用 Scrapy 框架的类似逻辑:
from http.cookies import SimpleCookie
from scrapy import FormRequest, Request, Spider
from scrapy.http import HtmlResponse
class AmazonSessionSpider(Spider):
"""
Amazon spider for extracting location cookies.
"""
name = "amazon.com:location-session"
address_change_endpoint = "/gp/delivery/ajax/address-change.html"
csrf_token_endpoint = (
"/gp/glow/get-address-selections.html?deviceType=desktop"
"&pageType=Gateway&storeContext=NoStoreName&actionSource=desktop-modal"
)
countries_base_urls = {
"US": "https://www.amazon.com",
"GB": "https://www.amazon.co.uk",
"DE": "https://www.amazon.de",
"ES": "https://www.amazon.es",
}
default_headers = {
"sec-fetch-site": "none",
"sec-fetch-dest": "document",
"accept-language": "ru-RU,ru;q=0.9",
"connection": "close",
}
def __init__(self, country: str, zip_code: str, *args, **kwargs):
super().__init__(*args, **kwargs)
self.country = country
self.zip_code = zip_code
def start_requests(self):
"""
Make start request to main Amazon country page.
"""
request = Request(
url=self.countries_base_urls[self.country],
headers=self.default_headers,
callback=self.parse_ajax_token,
)
yield request
def parse_ajax_token(self, response: HtmlResponse):
"""
Parse ajax token from response.
"""
yield response.request.replace(
url=self.countries_base_urls[self.country] + self.csrf_token_endpoint,
headers={
"anti-csrftoken-a2z": self.get_ajax_token(response=response),
**self.default_headers,
},
callback=self.parse_csrf_token,
)
def parse_csrf_token(self, response: HtmlResponse):
"""
Parse CSRF token from response and make request to change Amazon location.
"""
yield FormRequest(
method="POST",
url=self.countries_base_urls[self.country] + self.address_change_endpoint,
formdata={
"locationType": "LOCATION_INPUT",
"zipCode": self.zip_code,
"storeContext": "generic",
"deviceType": "web",
"pageType": "Gateway",
"actionSource": "glow",
"almBrandId": "undefined",
},
headers={
"anti-csrftoken-a2z": self.get_csrf_token(response=response),
**self.default_headers,
},
callback=self.parse_session_cookies,
)
def parse_session_cookies(self, response: HtmlResponse) -> dict:
"""
Return cookies dict if location changed successfully.
"""
json_data = response.json()
if not json_data.get("isValidAddress"):
return {}
return self.extract_response_cookies(response=response)
@staticmethod
def get_ajax_token(response: HtmlResponse) -> str:
"""
Extract ajax token from response.
"""
data = response.xpath("//input[@id='glowValidationToken']/@value").get()
if not data:
raise ValueError("Invalid page content")
return data
@staticmethod
def get_csrf_token(response: HtmlResponse) -> str:
"""
Extract CSRF token from response.
"""
csrf_token = response.css("script").re_first(r'CSRF_TOKEN : "(.+?)"')
if not csrf_token:
raise ValueError("CSRF token not found")
return csrf_token
@staticmethod
def extract_response_cookies(response: HtmlResponse) -> dict:
"""
Extract cookies from response object
and return it in valid format.
"""
cookies = {}
cookie_headers = response.headers.getlist("Set-Cookie", [])
for cookie_str in cookie_headers:
cookie = SimpleCookie()
cookie.load(cookie_str.decode("utf-8"))
for key, raw_value in cookie.items():
cookies[key] = raw_value.value
return cookies
外壳命令:
scrapy crawl amazon.com:location-session -a country=US -a zip_code=30332
关于web-scraping - 如何根据亚马逊的位置抓取数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66816666/
如本answer所述,如果浏览器不支持 e,可以设置后备游标。 G。 光标:抓取;。我现在的问题是获取这些图像。在我的驱动器上本地搜索“.cur”只给了我系统光标,其中 grab.cur 和 grab
以下代码在计算机上运行以从 Instagram 帐户中抓取数据。当我尝试在 VPS 服务器上使用它时,我被重定向到 Instagram 登录页面,因此脚本不起作用。 为什么当我在电脑上或服务器上时,I
我在使用 Ruby 和 Mechanize 将 POST 查询传递到站点的网站上。访问站点的查询基于 firebug,如下所示 param.PrdNo=-1¶m.Type=Prop¶m
我正在尝试抓取一个具有多个页面结果的网站,例如“1、2、3、4、5...”。 每个分页号都是到另一个页面的链接,我需要抓取每个页面。 到目前为止,我想出了这个: while lien = page.l
我正在使用 HtmlAgilityPack 在 C# Asp.Net 中执行 Scraping,到目前为止,我在从多个 Web 执行 Scratch 时没有遇到问题,但是,尝试弹出以下代码时出现错误
如果我有一个 css 文件做这样的事情 #foo:after{content:"bar;} ,有没有办法用 javascript 获取 :after 的内容?获取父元素的内容只返回 #foo 元素的内
问题是这样的: 我有一个 Web 应用程序 - 一个经常更改的通知系统 - 在一系列本地计算机上运行。该应用程序每隔几秒刷新一次以显示新信息。计算机仅显示信息,没有键盘或任何输入设备。 问题是,如果与
我想制作一个程序来模拟用户浏览网站和点击链接。必须启用 Cookie 和 javascript。我已经在 python 中成功地做到了这一点,但我想把它写成一种可编译的语言(python ide 不会
我制作了这个小机器人,它通过搜索参数列表进行处理。它工作正常,直到页面上有几个结果: product_prices_euros 给出了一半为空的项目列表。因此,当我与 product_prices_c
我需要找到一个单词的匹配项,例如: 在网上找到所有单词“学习”https://www.georgetown.edu/(结果:4个字)(您可以看到它按CTRL + F并搜索) 我有我的 Python 代
有一个站点\资源提供一些一般统计信息以及搜索工具的界面。这种搜索操作成本高昂,因此我想限制频繁且连续(即自动)的搜索请求(来自人,而不是来自搜索引擎)。 我相信有很多现有的技术和框架可以执行一些情报抓
这并不是真正的抓取,我只是想在网页中找到类具有特定值的 URL。例如: 我想获取 href 值。关于如何做到这一点的任何想法?也许正则表达式?你能发布一些示例代码吗?我猜 html 抓取库,比如 B
我正在使用 scrapy。 我正在使用的网站具有无限滚动功能。 该网站有很多帖子,但我只抓取了 13 个。 如何抓取剩余的帖子? 这是我的代码: class exampleSpider(scrapy.
我正在尝试从这个 website 中抓取图像和新闻 url .我定义的标签是 root_tag=["div", {"class":"ngp_col ngp_col-bottom-gutter-2 ng
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭上个月。 Improve this ques
我在几个文件夹中有数千个 html 文件,我想从评论中提取数据并将其放入 csv 文件中。这将允许我为项目格式化和清理它。例如,我在这个文件夹中有 640 个 html 文件: D:\My Web S
我在编写用于抓取网页的实用程序时遇到了一个问题。 我正在发送 POST 请求来检索数据,我模仿我正在抓取的网络行为(根据使用 fiddler 收集的信息)。 我已经能够自动替换我的 POST 中除 V
对于 Googlebot 的 AJAX 抓取,我在我的网站中使用“_escaped_fragment_”参数。 现在我查看了 Yandex 对我网站的搜索结果。 我看到搜索结果中不存在 AJAX 响应
我正在尝试抓取网站的所有结果页面,它可以工作,但有时脚本会停止并显示此错误: 502 => Net::HTTPBadGateway for https://website.com/id/12/ --
我是一个学习网络爬虫的初学者,由于某种原因我无法爬网this地点。当我在 Chrome 中检查它时,代码看起来不错,但是当我用 BeautifulSoup 阅读它时,它不再是可刮的。汤提到“谷歌分析”
我是一名优秀的程序员,十分优秀!