如何解决如何使用axios填写并在另一个网站上提交表格?
我当时是用Node.js制作一个抽奖机器人,最初是使用无头Puppeteer来自动完成抽奖表格的提交过程。有人告诉我,Puppeteer占用大量CPU,并且比Node.js中的请求模块(例如fetch,Axios等)慢。
过去2天,我一直在与Axios交流,但我实际上不知道如何填写和提交表单。如何填写和汇总上面在Axios中所述的表格?另外,就速度和CPU使用率而言,Axios是最佳选择吗?还是有更好的选择?
Here is an example for a form I would like to fill in.
这是我填写表格的人偶代码:
const { sizeSelectorsTitolo } = require('./selectors/sizes');
const accounts = require('./profiles/savedaccounts');
const { proxyList1 } = require('./profiles/proxylists');
async function titoloMain(url,size,shippingprofile,ppaccountnumber,proxygroup,instaaccountnumber){
let splitProxy = proxygroup.split(':');
let proxyUserLocal = splitProxy[2];
let proxyPassLocal = splitProxy[3];
let proxyPortLocal = splitProxy[1];
let proxyMainLocal = splitProxy[0];
let countrySelector = '';
//Getting size selector ready
let OurSizeSelector = 'sizeSelectorsTitolo.'
OurSizeSelector = OurSizeSelector.concat(size);
delete OurSizeSelector.property;
OurSizeSelector = eval(OurSizeSelector);
//Getting country selector
switch (shippingprofile.country){
case shippingprofile.country = "UK":
countrySelector = 'United Kingdom'
break;
case shippingprofile.country = "USA":
countrySelector = 'United States of America'
break;
case shippingprofile.country = "France":
countrySelector = 'France'
break;
case shippingprofile.country = "Spain":
countrySelector = 'Spain'
break;
case shippingprofile.country = "Germany":
countrySelector = 'Germany'
break;
case shippingprofile.country = "Canada":
countrySelector = 'Canada'
break;
};
//getting gender selectors
let localGender = '';
if (shippingprofile.gender == 'Male'){
localGender = 'Male'
} else {
localGender = 'Female'
};
const browser = await puppetteer.launch( {
headless: true,args: ['--disable-infobars',`--window-size=${1000.},${1000.}`,'--disable-features=IsolateOrigins,site-per-process',//ip and port
`${proxyMainLocal}:${proxyPortLocal}`
],ignoreDefaultArgs: ['--enable-automation']
});
const page = await browser.newPage();
//proxy settings
await page.authenticate({
username: proxyUserLocal,password: proxyPassLocal
});
await page.setUserAgent('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,like Gecko) Chrome/84.0.4147.125 Safari/537.36');
//now at the raffle page
console.log('on the raffle page')
await page.goto(url,{waitUntil:"networkidle2"});
console.log('filing out form...')
console.log('paypal')
await page.waitForSelector('#mce-EMAIL')
await page.type('#mce-EMAIL',accounts.paypalAccounts[ppaccountnumber].main,{delay:20})
console.log('name')
await page.type('#mce-FNAME',shippingprofile.firstname,{delay:20});
await page.type('#mce-LNAME',shippingprofile.surname,{delay:20});
console.log('shipping address')
await page.type('#mce-MMERGE5',shippingprofile.houseNum.concat(` ${shippingprofile.street}`),{delay:20});
await page.type('#mce-MMERGE8',shippingprofile.postcode,{delay:20});
await page.type('#mce-MMERGE12',shippingprofile.city,{delay:20});
await page.select('#mce-MMERGE3',countrySelector);
console.log('phone number')
await page.type('#mce-PHONE',shippingprofile.phoneNumber,{delay:20});
console.log('additional info')
await page.select('#mce-MMERGE9',localGender);
await page.select('#mce-MMERGE10','en');
console.log('instagram name')
await page.type('#mce-MMERGE7',accounts.instagram[instaaccountnumber].accountname,{delay:20});
console.log('selecting size')
await page.select('#mce-MMERGE6',OurSizeSelector)
console.log('clicking terms')
await page.waitForSelector('#mce-group\\[199\\]-199-0');
await page.waitFor(500);
await page.click('#mce-group\\[199\\]-199-0');
console.log('submitting')
await page.click('#mc-embedded-subscribe');
await page.waitFor(1000);
console.log(`done,check ${accounts.paypalAccounts[ppaccountnumber].main}`);
await browser.close()
};
这是axios的代码,我不知道我将如何定位输入字段以发布数据,所以我现在只记录标题:
const axios = require('axios')
async function test() {
axios.get('https://en.titoloshop.com/titolo/air-jordan-1-retro-high-og-bio-hack/#raffle')
.then(res => {
console.log(res.headers)
})
.catch(err => {
if (err.response) {
console.log('there was an error');
console.log(err.response.data);
console.log(err.response.status);
console.log(err.response.headers);
}
});
}
解决方法
TLDR::使用适当的表单数据对表单的POST
元素进行适当的编码,以发出action
请求。通过查看表单的name
或input
元素的select
属性,可以找到要发送的密钥。向下滚动查看代码。
首先,了解Puppeteer与请求模块(例如axios和node-fetch)之间的区别很重要。 Puppeteer用于控制浏览器并像使用用户一样使用网站,而axios仅用于发出HTTP请求。因此,您不能执行诸如单击按钮或填写表格之类的事情。
但是,提交表单通常只是将带有表单数据的HTTP请求发送到另一个URL。例如,这是该抽奖形式的HTML(简化):
<form
action="https://titolo.us6.list-manage.com/subscribe/post?u=652f80ec0adf2d7ac9588d0a1&id=8093f364b8"
method="post"
>
<div>
<label for="mce-EMAIL">Email Address* (PayPal)</label>
<input type="email" name="EMAIL" id="mce-EMAIL">
</div>
<!-- first name,last name,address,postcode,city -->
<div>
<label for="mce-MMERGE3">Country*</label>
<select name="MMERGE3" id="mce-MMERGE3">
<option value=""></option>
<option value="Switzerland">Switzerland</option>
<!-- more countries... -->
</select>
</div>
<!-- the rest of the inputs... -->
<div>
<strong>Terms & Conditions </strong>
<ul>
<li>
<input type="checkbox" name="group[243][1]" id="mce-group[243]-243-0">
<label for="mce-group[243]-243-0">I agree</label>
</li>
</ul>
</div>
<!-- more stuff... -->
<!-- real people should not fill this in and expect good things - do not remove this or risk form bot signups-->
<div style="position: absolute; left: -5000px">
<input
type="text"
name="b_652f80ec0adf2d7ac9588d0a1_8093f364b8"
tabindex="-1"
value=""
>
</div>
<div>
<input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe">
</div>
</form>
让我们分解一下。
-
<form action="..." method="post'>
:表单会将帖子主体中的数据POST
到action
属性中指定的URL。它将根据enctype
属性进行编码。在这种情况下,它将是一个application/x-www-form-urlencoded
字符串(例如key1=value1&key2=value2
),这是默认设置。 -
<input type="email" name="EMAIL" id="mce-EMAIL">
:输入的电子邮件将是帖子正文中的EMAIL
键的值(由name
属性指示)。 -
<select name="MMERGE3" id="mce-MMERGE3">
:所选选项将是MMERGE3
键的值。-
<option value="Switzerland">
每个选项都有一个value
属性,该属性指定要在帖子正文中发送的字符串。这不必与文本内容相同。如果不存在,则将发送元素的文本内容。
-
-
<input type="checkbox" value="1" name="group[243][1]" id="mce-group[243]-243-0">
这是一个复选框输入。如果选中此复选框,则表单主体中的group[243][1]
(name
属性)将是1
(value
属性,默认为on
)。如果未选中,则group[243][1]
将不存在。 -
<input type="text" name="b_652f80ec0adf2d7ac9588d0a1_8093f364b8" tabindex="-1" value="">
根据评论,这是绝对不能填写的输入,只是为了防止机器人注册抽奖活动(不是讽刺意味?)。 -
<input type="submit" value="Subscribe" name="subscribe" id="mc-embedded-subscribe">
这是“提交”按钮。除非存在name
属性(就像其他任何input
一样),否则不提交此值,因此在这种情况下,将有一个名为subscribe
的键,其值为{{1 }}(来自Subscribe
属性)。默认的value
属性因浏览器而异:value
有关提交表单的工作方式的更多信息,请参见Sending form data on MDN。
因此,要在不使用Puppeteer的情况下提交此表单,您需要使用适当的URL编码的表单值作为表单数据来发起<input type="submit">
请求。您可以在axios(documentation)中进行此操作:
POST
此代码应提交表单,就像用户填写表单并在其网站上提交一样。很有可能,实际上并不是所有这些都需要(例如订阅按钮和不可见的输入),但是为了防万一,我在此包括它们。
注意:网站要求您选择一种希望从公司那里听到的方式:时事通讯(const url = 'https://titolo.us6.list-manage.com/subscribe/post?u=652f80ec0adf2d7ac9588d0a1&id=8093f364b8'
axios.post(url,new URLSearchParams({
EMAIL: accounts.paypalAccounts[ppaccountnumber].main,FNAME: shippingprofile.firstname,LNAME: shippingprofile.surname,// Address
MMERGE5: shippingprofile.houseNum.concat(` ${shippingprofile.street}`),// Postcode
MMERGE8: shippingprofile.postcode,// City
MMERGE12: shippingprofile.city,// Country
MMERGE3: countrySelector,PHONE: shippingprofile.phoneNumber,// Gender
MMERGE9: localGender,// Language
MMERGE10: 'en',// Size
MMERGE6: OurSizeSelector,// Instagram account name
MMERGE7: accounts.instagram[instaaccountnumber].accountname,// T&Cs
'group[243][1]': '1',// That invisible input
b_652f80ec0adf2d7ac9588d0a1_8093f364b8: '',// Subscribe button
subscribe: 'Subscribe'
}))
)和/或抽奖信息(name="gdpr[695]"
)。这两个复选框都具有name="gdpr[699]"
,因此,如果要作为表单的一部分提交这些复选框,只需将value="Y"
和/或'gdpr[695]': 'Y'
添加到'gdpr[699]': 'Y'
构造函数中。>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。