在。txt文件中有30.000个url要刮,当我制作程序时,我用10个url测试它,一切都很好,当我制作30K url文件时。txt几分钟后崩溃,我想它开始读取。txt文件,然后由于内存问题崩溃,这里是控制台输出和我的代码。处理这样的文件最好的方法是什么?
致命错误:无效标记-压缩接近堆限制分配失败-JavaScript堆内存不足1:0x100BA0C4A节点::abort()(.cold.1)[/usr/local/bin/node]2:0x100084961节点::fatalerror(char const*,char const*)[/usr/local/bin/node]3:0x100084A89节点::onfatalerror(char const*,char const*)[/usr/local/bin/node]4:0x10017Fa4d V8::Utils::ReportoomFailure(V8::internal::isolate*10017f9f7 v8::internal::v8::fatalprocessoutofmemory(V8::internal::isolate*,char const*,bool)[/usr/local/bin/node]6:0x100299BAF v8::internal::heap::fatalprocessoutofmemory(char const*)[/usr/local/bin/node]7:0x10029AF4c v8::internal::heap::markcompactPrologue()/usr/local/bin/node]9:0x1002975AB V8::internal::heap::collectgarbage(V8::internal::AllocationSpace,V8::internal::GarbageCollectionReason,V8::GcCallback标志)[/usr/local/bin/node]10:0x100296A2A V8::internal::heap::handlegcrequest()[/usr/local/bin/node]11:0x10026D9A5 V8::internal::stackguard::handleinterrupts()[/usr/local/bin/node]12:0x1004E1383 V8::internal::runtime_stackguard(int,无符号long*,V8::internal::isolate*)[/usr/local/bin/node]bin/node]14:0x10073c5fb Builtins_StringPrototypeMatch[/usr/local/bin/node]15:0x267b75f209cb zsh:abort node scrape.js
let cheerio = require('cheerio');
let request = require('request');
let UserAgent = require('user-agents');
let axios = require('axios');
const fileUrlErrors = "UrlsWithErrors.txt";
const async = require('async')
let Promise = require("bluebird");
let userAgent = new UserAgent({ deviceCategory: 'desktop' });
let options = {
headers: { userAgent }
};
let exec = require('child_process').exec;
const mysql = require('mysql2/promise');
let con = mysql.createPool({
host: "xxx.xxx.xxx.xxx",
user: "xxx",
password: "xxxx",
database: "xxx"
});
async function run() {
let file = fs.readFileSync('urls.txt');
let urls = file.toString().split('\r\n');
console.log(urls);
const numeroUrl = urls.length;
let urlsArray = [];
console.log("numeroUrl : " + numeroUrl);
for (let i = 1; i < numeroUrl; i++) {
for (let y = 1; y < 6; y++) {
urlsArray.push(urls[y-1] + '&page=' + y);
}
}
Promise.map(urlsArray, parseUrl, {concurrency: 10}).then(function(data) {
// all done here
console.log("Done!!!");
});
}
async function parseUrl(url) {
try {
let response = await axios.get(url, {
headers: {
'User-Agent': new UserAgent()
}
});
console.log(url + " " + response.status);
if (response.status >= 201) {
fs.appendFile(fileUrlErrors, '\n' + url + ' - ' + response.status, (error) => {
if (error) {
console.error(`Could not save the url status error to a file: ${error}`);
return;
}
console.log('Saved Url error to ' + fileUrlErrors);
});
} else if (response.status == 200) {
let $ = cheerio.load(response.data);
prodotti = $(".item");
let items = $(prodotti).get();
for (let item of items) {
let title = $(".title", item).text();
if (!title) {
title = $(".title2", item).text();
}
let price = $(".price", item).text();
if (!price) {
price = $(".price2", item).text();
}
if (title) {
const prodotto = [
[
title,
price]
];
let result = await con.query("INSERT INTO Items (title, price) VALUES ? ON DUPLICATE KEY UPDATE price=VALUES(price)", [prodotto]);
console.log('Prodotto ' + title + ' inserito nel DB.');
console.log(prodotto);
}
}
}
} catch (error) {
//console.error(error);
if (error.response) {
// Request made and server responded
await fs.appendFile(fileUrlErrors, '\n' + url + " - " + error.response.status, (error) => {
if (error) {
console.error(`Could not save the url status error to a file: ${error}`);
return;
}
console.log('Saved Url error to ' + fileUrlErrors);
});
}
}
}
run().then(() => {
console.log("Done!");
}).catch(err => {
console.log(err);
});
正如在注释中所讨论的,parseurl()
函数混合了promise和普通的异步回调,这是一个灾难。你真的不能把它们混在一起。最好的解决方案是使用promise执行所有的异步控制流,如果您有一些非promise返回异步回调,那么可以使用util.promisify()
手动promise它们,使用API的正确promise版本,或者获得包含promise支持的库的正确版本。
您已经将所有内容转换为promise控制流,然后可以使用Async
和await
和其他promise控制流工具,只有这样,parseurl()
函数才会返回一个promise,该promise只有在所有底层异步操作完成后才会解析,并且只有这样,您才会有正确的错误传播。
下面的示例修复了parseurl()
,以便对所有异步操作正确使用promise,然后在for
循环中使用await
一次处理一个URL,这样就不会同时占用太多内存:
const fs = require('fs');
async function run() {
const file = fs.readFileSync('urls.txt');
const urls = file.toString().split('\r\n');
// count the number of urls inside .txt file
const numberOfUrls = urls.length;
console.log("There are : " + numberOfUrls + " urls");
// Add page to url and use the scrape function
for (let i = 1; i < numberOfUrls; i++) {
for (let y = 1; y < 6; y++) {
let url = urls[y - 1] + '&page=' + y;
await parseUrl(url);
}
}
async function parseUrl(url) {
try {
const response = await axios.get(url, {
headers: {
'User-Agent': new UserAgent()
}
});
if (response.status >= 201) {
await fs.promises.appendFile(fileUrlErrors, '\n' + url + ' - ' + response.status);
} else if (response.status == 200) {
const $ = cheerio.load(response.data);
const prodotti = $(".result");
// get items into a normal array so we can use a normal for loop
const items = $(prodotti).get();
for (let item of items) {
const title = $("title", item).text();
const code = $(".code", item).text();
if (asin[1]) {
const prodotto = [
[title, code]
];
// promise support in your mysql database requires the mysql2 module
const result = await con.query("INSERT INTO Items (title, code) VALUES ? ON DUPLICATE KEY UPDATE code=VALUES(code)", [prodotto]);
console.log('Prodotto ' + code + ' inserito nel DB.');
console.log(prodotto);
}
}
}
} catch (error) {
console.error(error);
throw error; // propagate error back to caller
}
}
}
run().then(() => {
console.log("all done");
}).catch(err => {
console.log(err);
});
注意,NPM上的mysql2模块是获得对mysql数据库(我猜这就是您正在使用的数据库)promise支持的最佳位置。您可能还必须更改设置数据库连接的其他代码以使用promise(此处未显示的代码)。
变更摘要:
fs.promises.appendfile()
以获得promise支持。let
或const
。不使用var
.mysql2
,以便可以使用对con.query()
if
和if
更改为if
和else if
,因为这正是您的逻辑。file.tostring().split('\r\n')
已经是一个数组,所以不需要在它上使用object.keys()
来获取长度。您可以直接引用数组上的.length
属性。我有一个小型java应用程序,运行一组计算量大的任务。为了处理这些任务,我使用了一个外部库,它通过本机方法和一些C代码完成大部分计算。不幸的是,在解决一个任务后,库会遭受严重的内存泄漏,因此每次应用程序执行只能解决一个任务。 库中的编码人员知道内存问题,但尚未修复,可能永远也不会修复(这与java垃圾收集器不能正确使用本机inferface有关)。由于这个特定的库没有其他选择,我正在寻找通过顺序执
本文向大家介绍内存泄漏和内存溢出是什么?一般怎么处理内存泄漏?相关面试题,主要包含被问及内存泄漏和内存溢出是什么?一般怎么处理内存泄漏?时的应答技巧和注意事项,需要的朋友参考一下 (1)内存溢出(OOM)和内存泄露(对象无法被回收)的区别。 (2)引起内存泄露的原因 (3)内存泄露检测工具 ------>LeakCanary 内存溢出 out of memory:是指程序在申请内存时,没有足够的内
问题内容: 我多次问到这个问题。有什么好的答案 问题答案: Java中会不会发生内存泄漏? 答案是,这取决于您正在谈论的是哪种内存泄漏。 经典C / C ++内存泄漏是在应用程序或对象完成使用后忽略时发生的,并且会泄漏。循环引用是这种情况的一个子案例,其中应用程序很难知道何时使用/ ,因此忽略了这样做。相关问题是应用程序在释放对象后使用对象,或尝试释放对象两次。(您可以将后者称为内存泄漏,或者仅是
本文向大家介绍请你说说C++如何处理内存泄漏?相关面试题,主要包含被问及请你说说C++如何处理内存泄漏?时的应答技巧和注意事项,需要的朋友参考一下 使用varglind,mtrace检测
我有一个关于接口的问题,比如: 现在,我需要这只猫去抓一只老鼠void catchMouse(){std::cout 有几种可能的解决方案,但看起来都不好。 > 在IAnim中添加一个方法,然后使用AnimalFactory创建猫后,我可以从IAnimal调用catchMouse()方法。但是catchMouse并不适用于所有动物,狗不catchMouse。将方法添加到IEM会污染界面,嗅到代码。
我试图在一个特定文件夹中保存多个图像第一个图像保存正确,但下一个图像只是替换第一个图像。如何保存多个图像?如何动态命名并使用相同的名称保存图像,但使用不同的扩展名,如image、image1、image2。。。下面是我的代码