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