Python线程-内部缓冲区错误-内存不足

Python线程-内部缓冲区错误-内存不足,python,beautifulsoup,out-of-memory,web-crawler,python-multithreading,Python,Beautifulsoup,Out Of Memory,Web Crawler,Python Multithreading,我使用urllib和beautifulsoup制作了一个简单的网络爬虫,从网页上的表中提取数据。为了加快数据拉取,我尝试使用线程,但出现以下错误: “内部缓冲区错误:内存分配失败:缓冲区增长” 此消息出现多次,然后指出: “内存不足” 谢谢你的帮助 from bs4 import BeautifulSoup from datetime import datetime import urllib2 import re from threading import Thread stockData

我使用urllib和beautifulsoup制作了一个简单的网络爬虫,从网页上的表中提取数据。为了加快数据拉取,我尝试使用线程,但出现以下错误: “内部缓冲区错误:内存分配失败:缓冲区增长” 此消息出现多次,然后指出: “内存不足”

谢谢你的帮助

from bs4 import BeautifulSoup
from datetime import datetime
import urllib2
import re
from threading import Thread

stockData = []

#Access the list of stocks to search for data
symbolfile = open("stocks.txt")
symbolslist = symbolfile.read()
newsymbolslist = symbolslist.split("\n")

#text file stock data is stored in
myfile = open("webcrawldata.txt","a")

#initializing data for extraction of web data
lineOfData = ""
i=0

def th(ur):
    stockData = []
    lineOfData = ""
    dataline = ""
    stats = ""
    page = ""
    soup = ""
    i=0
    #creates a timestamp for when program was won
    timestamp = datetime.now()
    #Get Data ONLINE
    #bloomberg stock quotes
    url= "http://www.bloomberg.com/quote/" + ur + ":US"
    page = urllib2.urlopen(url)
    soup = BeautifulSoup(page.read())
    #Extract key stats table only
    stats = soup.find("table", {"class": "key_stat_data" })
    #iteration for <tr>
    j = 0
    try:
        for row in stats.findAll('tr'):
            stockData.append(row.find('td'))
            j += 1
        except AttributeError:
            print "Table handling error in HTML"
    k=0
    for cell in stockData:
        #clean up text
        dataline = stockData[k]
        lineOfData = lineOfData + " " + str(dataline)
        k += 1
    g = str(timestamp) + " " + str(ur)+ ' ' + str(lineOfData) + ' ' +  ("\n\n\n")    
    myfile.write(g)
    print (ur + "\n")
    del stockData[:]
    lineOfData = ""
    dataline = ""
    stats = None
    page = None
    soup = None
    i += 1

threadlist = []

for u in newsymbolslist:
    t = Thread(target = th, args = (u,))
    t.start()
    threadlist.append(t)

for b in threadlist:
    b.join()enter code here
从bs4导入美化组
从日期时间导入日期时间
导入urllib2
进口稀土
从线程导入线程
stockData=[]
#访问股票列表以搜索数据
symbolfile=open(“stocks.txt”)
symbolslist=symbolfile.read()
newsymbolslist=symbolslist.split(“\n”)
#文本文件股票数据存储在
myfile=open(“webcrawldata.txt”、“a”)
#初始化数据以提取web数据
lineOfData=“”
i=0
定义th(ur):
stockData=[]
lineOfData=“”
dataline=“”
stats=“”
page=“”
汤=“”
i=0
#为程序赢得的时间创建时间戳
timestamp=datetime.now()
#在线获取数据
#彭博社股票报价
url=”http://www.bloomberg.com/quote/“+ur+”:美国”
page=urlib2.urlopen(url)
soup=BeautifulSoup(page.read())
#仅提取密钥统计表
stats=soup.find(“表”,{“类”:“key\u stat\u data”})
#迭代
j=0
尝试:
对于stats.findAll('tr')中的行:
stockData.append(row.find('td'))
j+=1
除属性错误外:
打印“HTML中的表格处理错误”
k=0
对于stockData中的单元格:
#清理文本
数据线=股票数据[k]
lineOfData=lineOfData+“”+str(数据线)
k+=1
g=str(时间戳)+''+str(ur)+''+str(lineOfData)+''+(“\n\n\n”)
myfile.write(g)
打印(ur+“\n”)
del stockData[:]
lineOfData=“”
dataline=“”
统计数据=无
页码=无
汤=无
i+=1
线程列表=[]
对于新闻符号列表中的u:
t=线程(目标=th,参数=(u,))
t、 开始()
threadlist.append(t)
对于线程列表中的b:
b、 join()在此处输入代码

不要重新发明轮子并使用:

Scrapy是一个用于抓取网站和应用程序的应用程序框架 提取可用于广泛应用的结构化数据 有用的应用程序,如数据挖掘、信息处理或 历史档案

想想看-可伸缩性/并行化/性能问题已经为您解决了-您真的想继续潜入python中线程的奇妙世界,让您的代码闻起来可疑,影响CPU和内存限制,处理冲突,最后,使您的代码无法调试和维护,而不是专注于提取和收集数据?而且,即使使用
gevent
,我怀疑您的最终代码在任何方面都不会像基于Scrapy实现的代码那样简单易读。为什么不使用经过大量用户测试和使用的工具,这被证明是在网络抓取python世界中创建的最好的工具

下面是一个正在工作的爬行器,它以类似的方式刮取引号:

from scrapy.spider import Spider
from scrapy.item import Item, Field
from scrapy.http import Request


class BloombergItem(Item):
    ur = Field()
    parameter = Field()
    value = Field()


class BloombergSpider(Spider):
    name = 'bloomberg'
    allowed_domains = ['www.bloomberg.com']

    def start_requests(self):
        with open("stocks.txt") as f:
            for ur in f:
                yield Request("http://www.bloomberg.com/quote/%s:US" % ur)

    def parse(self, response):
        for parameter in response.css('table.key_stat_data tr'):
            item = BloombergItem()
            item['ur'] = response.xpath('//title/text()').extract()[0].split(':')[0]
            item['parameter'] = parameter.xpath('th/text()').extract()[0]
            item['value'] = parameter.xpath('td/text()').extract()[0]
            yield item
如果
stocks.txt
的内容是:

AAPL
spider将输出(例如,如果您选择以JSON格式输出):


从Scrapy开始的一个好地方是。

开始的每个线程都有一个线程堆栈大小,其大小为8KB Linux系统中的默认值(请参见
ulimit-s
),因此线程所需的内存总数将超过20GB

您可以使用线程池,例如10个线程;当一 完成了它的工作,它还有另一项任务要做

但是:一般来说,运行比CPU核更多的线程是毫无意义的。所以我的 建议停止使用线程。你可以使用你喜欢的库 在不使用操作系统级线程的情况下执行完全相同的操作

gevent的优点是猴子补丁:你可以看出来 为了改变Python标准库的行为,这将 透明地线程到“greenlet”对象中(参见文档 有关更多详细信息)。所提出的并发类型是 特别适合您正在进行的密集I/O

在代码中,只需在开头添加以下内容:

from gevent import monkey; monkey.patch_all()
在同一台计算机上同时打开的文件描述符不能超过1024个 Linux系统默认情况下(请参见
ulimit-n
),因此您必须增加
如果您希望同时打开2700个文件描述符,则此限制。

您在
newsymbolslist
中有多少项?大约2700个纽约证券交易所的所有符号,因此您将并行启动2700个线程?谢谢!我安装了gevent并按照建议运行。它改进了程序,使它比我最初编写的代码更深入。虽然它仍然没有内存并且冻结了。我一直在查看gevent文档,看看是否可以修改它来阻止这种情况。你需要确切地了解什么在消耗内存。你适当地释放资源了吗?我不这么认为。有没有具体的教程或示例可以帮助我做到这一点?我一直在研究如何使用gevent。
from gevent import monkey; monkey.patch_all()