看看网络工具,你做对了。我发现最好放大您在网络选项卡中给出的概述。您可以在浏览器中选择任何比例的操作。查看发生了哪些请求。因此,当您单击搜索时,您可以专注于请求和响应的开始。它为您提供了两个请求,一个将信息发布到服务器,一个将信息抓取到单独的 url。
建议
我看过该网站的建议是可能使用 selenium,这是一个模仿浏览器活动的包。下面你会看到我对请求的研究。本质上,该表单会在您每次进行搜索时生成一个唯一标记。您必须复制才能获得正确的响应。这很难提前知道。
话虽如此,您可以使用 selenium 模拟浏览器活动并自动输入邮政编码并自动单击搜索按钮。然后,您可以获取页面源 HTML 并使用 beautifulsoup 对其进行解析。这是一个最小的可重现示例,向您展示了这一点。
编码示例
from selenium import webdriver
from bs4 import BeautifulSoup
driver = webdriver.Chrome(executable_path=r'c:\users\aaron\chromedriver.exe')
url = 'https://ecitizen.aberdeencity.gov.uk/publicaccesslive/selfservice/services/counciltax/bandsearch.htm'
driver.get(url)
driver.find_element_by_id('postcode').send_keys('AB24 4DE')
driver.find_element_by_xpath('//input[@class="btn btn-primary cap-submit-inline"]').click()
soup = BeautifulSoup(driver.page_source,'html.parser')
还有让浏览器无头的空间,所以它不会弹出,你得到的只是解析后的 html。
代码说明
我们正在从 selenium 导入 webdriver,这提供了加载浏览器所需的模块。然后我们创建该 webdriver 的实例,在这种情况下,我使用的是 chrome,但您可以使用 firefox 或其他浏览器。
您需要从这里下载 chromedriver,https://chromedriver.chromium.org/。 Webdriver 使用它来打开浏览器。
我们使用get webdriver get方法让chromedriver去到我们想要的特定页面。
Webdriver 有一个查找元素的列表...您可以使用。这里最简单的是find_element_by_id。我们可以在 HTML 中找到输入框的 id 用于输入邮政编码,这里我已经做到了。 Send_keys 将发送我们想要的任何文本,在本例中是 AB24 4DE。
find_element_by_xpath 采用 XPATH 选择器。 '//' 遍历所有 DOM,我们选择输入,[@class=""] 部分选择特定的输入标记类。我们想要提交按钮。 click() 方法将点击该浏览器。
一旦点击完成,我们就会获取页面源代码,这是必要的,因为我们随后将其输入到 BeuatifulSoup,它将为我们提供所需邮政编码的解析 HTML。
对 HTTP 请求进行逆向工程
下面是真正的教育,除非有人可以在向服务器发送请求之前获得唯一令牌。以下是网站在搜索表单方面的工作方式。
从本质上看,它是将 cookie、标头、参数和数据发送到服务器。 cookie 有一个会话 ID,在我的测试中似乎没有改变。数据变量是您可以更改邮政编码的地方,但重要的是,每次您想要进行搜索时 ABCtoken 都会更改,并且参数是对服务器的检查,以确保它不是机器人。
作为 HTTP POST 请求的示例。我们发送这个
cookies = {
'JSESSIONID': '1DBAC40138879EB418C14AD83C05AD86',
}
headers = {
'Connection': 'keep-alive',
'Cache-Control': 'max-age=0',
'Upgrade-Insecure-Requests': '1',
'Origin': 'https://ecitizen.aberdeencity.gov.uk',
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Sec-Fetch-Site': 'same-origin',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-User': '?1',
'Sec-Fetch-Dest': 'document',
'Referer': 'https://ecitizen.aberdeencity.gov.uk/publicaccesslive/selfservice/services/counciltax/bandsearch.htm',
'Accept-Language': 'en-US,en;q=0.9',
}
params = (
('action', 'validateData'),
)
data = {
'postcode': 'AB24 2RX',
'address': '',
'startSearch': 'Search',
'ABCToken': '35fbfd26-cb4b-4688-ac01-1e35bcb8f63d'
}
到
https://ecitizen.aberdeencity.gov.uk/publicaccesslive/selfservice/services/counciltax/bandsearch.htm
然后它在这里使用相同的 JSESSIONID 和唯一的 ABCtoken 执行 HTTP GET 请求,以获取您想要的数据 bandsearchresults.html
'https://ecitizen.aberdeencity.gov.uk/publicaccesslive/selfservice/services/counciltax/bandsearchresults.htm'
所以它正在创建一个 JSESSIONID,这对于我的测试中的任何邮政编码似乎都是相同的。然后,当您使用相同的 JSESSIONID 并使用 ABCtoken 时,它会提供搜索结果 URL,您将获得正确的数据。