如何在通过分页进行网页抓取时与 .aspx 服务器保持会话?

How to maintain a session with .aspx server while web scraping through pagination?

我无法与 .aspx 服务器保持会话。我正在尝试通过分页来抓取数据,但它一直告诉我 "The Results have expired. Please resubmit the search." 我已经尝试维护 cookie,所以我不认为这是问题所在,除非我不知何故做错了?

我必须首先向以下 URL 发出 GET 请求来导航:

https://www.wandsworth.gov.uk/planning-and-building-control/search-planning-applications/

以下是我用来发出请求的代码。

首先这些都是我的要求

const cheerio = require('cheerio');
const url = require('url');
const rp = require('request-promise');
const ss = require('string-similarity');
const tc = require('tough-cookie');

这是我提出请求的方式

var options = {
  uri: 'https://www.wandsworth.gov.uk/planning-and-building-control/search-planning-applications/',
  transform: function(body){ return cheerio.load(body) },
  method: 'GET'
}

var $ = await rp(options);

现在我提取我需要的信息以便成功发出 post 请求,然后我使用 'string-similarity' 包找到一个 select 元素,该元素与一个标签紧密匹配匹配我的输入。

// Extract selectable elements
var obj_collection = $('#cboStreetReferenceNumber')[0].children;
var collection = []; // array of inner strings for each select element

// Push innerHTML strings to collection
for(let i=0; i<obj_collection.length; i++){
     try {
         collection.push(obj_collection[i].children[0].data);
     } catch(e) {
         collection.push('');
     }
}

// Find the best match for our given address
var matches = ss.findBestMatch(address, collection);
var cboStreetReferenceNumber=
obj_collection[matches.bestMatchIndex].attribs.value;

// These are used to verify us
var __VIEWSTATE = $('#__VIEWSTATE')[0].attribs.value;
var __VIEWSTATEGENERATOR = $('#__VIEWSTATEGENERATOR')[0].attribs.value;
var __EVENTVALIDATION = $('#__EVENTVALIDATION')[0].attribs.value;
var cboMonths = 1;
var cboDays = 1;
var csbtnSearch = 'Select';
var rbGroup = 'rbNotApplicable';

// Modify options
options.uri = $('#M3Form')[0].attribs.action;
options.method = 'POST';
options.form = { 
cboStreetReferenceNumber,
__VIEWSTATE,
__VIEWSTATEGENERATOR,
__EVENTVALIDATION,
cboMonths,
cboDays,
csbtnSearch,
rbGroup
};      
options.followAllRedirects = true;
options.resolveWithFullResponse = true;
delete options.transform;

现在有了这些选项,我就可以向我要查找的数据的第 1 页提出请求了。

// method: @POST
// link: "Planning Explorer"
var body = await rp(options);
var $ = cheerio.load(body.body);
console.log(body.request);
var Referer = 'https://planning1.wandsworth.gov.uk' + body.req.path;

var scroll_uri = 'https://planning1.wandsworth.gov.uk/Northgate/PlanningExplorer/Generic/StdResults.aspx?PT=Planning%20Applications%20On-Line&PS=10&XMLLoc=/Northgate/PlanningExplorer/generic/XMLtemp/ekgjugae3ox3emjpzvjtq045/c6b04e65-fb83-474f-b6bb-2c9d4629c578.xml&FT=Planning%20Application%20Search%20Results&XSLTemplate=/Northgate/PlanningExplorer/SiteFiles/Skins/Wandsworth/xslt/PL/PLResults.xslt&p=10';
options.uri = scroll_uri;
delete options.form;
delete options.followAllRedirects;
delete options.resolveWithFullResponse;
options.method = 'GET';
options.headers = {};
options.headers.Referer = Referer;
options.transform = function(body){
     return cheerio.load(body);
}

var $ = await rp(options);

进入下一页后,我会得到一个包含 10 个项目的 table 和一些分页,如果根据我的 POST 请求有超过 10 个项目可用的话。

一切顺利,直到我尝试分页到第 2 页。生成的 HTML 正文告诉我我的搜索已过期,我需要重新提交搜索。这意味着返回到第 1 步并再次提交 POST 请求,但是这将始终将我带到分页的第 1 页。

因此,我需要想办法在 'scroll' 浏览其页面时与该服务器保持连接。

我正在使用 node.js 和请求承诺来提出我的请求。

以下是我的代码:

我已经尝试过在请求之间维护 cookie。

此外,__VIEWSTATE 应该不是问题,因为对第 2 页的请求应该是 GET 请求。

我能够通过使用无头浏览器 "Puppeteer" 找到解决方法,以保持与服务器的连接。但是,我仍然不知道如何通过原始请求来解决这个问题。