运行 一段时间后,多线程爬虫变得越来越慢
Multithreading crawler get slower and slower after running for some time
我在Windows下写了一个多线程网络爬虫。我使用的库是 requests
和 threading
。我发现程序在 运行ning 一段时间后变得越来越慢(大约 500 页)。当我停止程序并再次 运行 时,程序再次加速。似乎有许多挂起的连接,导致速度变慢。我该如何解决这个问题?
我的代码:
import requests, threading,queue
req = requests.Session()
urlQueue = queue.Queue()
pageList = []
urlList = [url1,url2,....url500]
[urlQueue.put(i) for i in urlList]
def parse(urlQueue):
try:
url = urlQueue.get_nowait()
except:
break
try:
page = req.get(url)
pageList.append(page)
except:
continue
if __name__ == '__main__':
threadNum = 4
threadList = []
for i in threadNum:
t = threading.Thread(target=(parse),args=(urlQueue,))
threadList.append(t)
for thread in threadList:
thread.start()
for thread in threadList:
thread.join()
我搜索了这个问题。有回答说是Linux下TCP的重用回收问题。我不太明白这个答案。答案如下。我把中文的回答翻译过来了
- 在Linux中键入命令shell:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
- 发现
TIME_WAIT
快2W了。所以,一定有很多TCP连接。
- 使用以下代码分别设置TCP的重用时间和回收时间:
echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
、echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
这个答案似乎是正确的。应该是网络问题。在 Windows.
下我应该如何解决这个问题
多线程爬虫将耗尽 TCP 连接。我们需要设置 TcpTimedWaitDelay
来快速重用和回收 TCP 连接。我们可以通过手动更改regedit
或输入代码来解决问题。
如何使用代码在 Windows 上执行此操作:
(需要以管理员身份运行密码,否则会报错)
import win32api,win32con
key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, r'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters', 0, win32con.KEY_SET_VALUE)
win32api.RegSetValueEx(key, 'TcpTimedWaitDelay', 0, win32con.REG_SZ, '30')
win32api.RegCloseKey(key)
如何在 Windows 上手动完成:
- 打开
RUN
,然后键入 regedit
- 查找:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters
- 点击
Edit
- New
- Expandable String Value
- 创建
TcpTimedWaitDelay
(如果该条目已经存在,则不需要创建)
- 改成30。(TCP取值范围30到300秒,默认120秒,默认太长
很适合多线程爬虫。)
感谢大家对问题的贡献。这对很多人都有帮助。
我在Windows下写了一个多线程网络爬虫。我使用的库是 requests
和 threading
。我发现程序在 运行ning 一段时间后变得越来越慢(大约 500 页)。当我停止程序并再次 运行 时,程序再次加速。似乎有许多挂起的连接,导致速度变慢。我该如何解决这个问题?
我的代码:
import requests, threading,queue
req = requests.Session()
urlQueue = queue.Queue()
pageList = []
urlList = [url1,url2,....url500]
[urlQueue.put(i) for i in urlList]
def parse(urlQueue):
try:
url = urlQueue.get_nowait()
except:
break
try:
page = req.get(url)
pageList.append(page)
except:
continue
if __name__ == '__main__':
threadNum = 4
threadList = []
for i in threadNum:
t = threading.Thread(target=(parse),args=(urlQueue,))
threadList.append(t)
for thread in threadList:
thread.start()
for thread in threadList:
thread.join()
我搜索了这个问题。有回答说是Linux下TCP的重用回收问题。我不太明白这个答案。答案如下。我把中文的回答翻译过来了
- 在Linux中键入命令shell:
netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
- 发现
TIME_WAIT
快2W了。所以,一定有很多TCP连接。 - 使用以下代码分别设置TCP的重用时间和回收时间:
echo "1" > /proc/sys/net/ipv4/tcp_tw_reuse
、echo "1" > /proc/sys/net/ipv4/tcp_tw_recycle
这个答案似乎是正确的。应该是网络问题。在 Windows.
下我应该如何解决这个问题多线程爬虫将耗尽 TCP 连接。我们需要设置 TcpTimedWaitDelay
来快速重用和回收 TCP 连接。我们可以通过手动更改regedit
或输入代码来解决问题。
如何使用代码在 Windows 上执行此操作: (需要以管理员身份运行密码,否则会报错)
import win32api,win32con
key = win32api.RegOpenKey(win32con.HKEY_LOCAL_MACHINE, r'SYSTEM\CurrentControlSet\Services\Tcpip\Parameters', 0, win32con.KEY_SET_VALUE)
win32api.RegSetValueEx(key, 'TcpTimedWaitDelay', 0, win32con.REG_SZ, '30')
win32api.RegCloseKey(key)
如何在 Windows 上手动完成:
- 打开
RUN
,然后键入regedit
- 查找:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Tcpip\Parameters
- 点击
Edit
-New
-Expandable String Value
- 创建
TcpTimedWaitDelay
(如果该条目已经存在,则不需要创建) - 改成30。(TCP取值范围30到300秒,默认120秒,默认太长 很适合多线程爬虫。)
感谢大家对问题的贡献。这对很多人都有帮助。