2015-08-21 88 views
1

在你的下方看到我的抓取工具的蓝图。我想我可以用多线程加速它,但我不能。很多时候,当我加载一个网页时,网络服务器速度很慢,然后爬上另一个多线程加载速度更快的网页会很好。但它不会更快。为什么?为什么我不能加快python中的多线程爬行?

def start_it(): 
    while(True): 
     get_urls() 

def get_urls(): 
    response = urllib2.urlopen(url) 
    page_source = str(response.read()) 

pool = ThreadPool(10) 

pool.map(start_it()) 

好吧我测试过,如果线程并行运行,它们不是:/我在做什么错了?

def start_it(): 

    x = random.random() 
    while(True): 
     get_urls(x) 

def get_urls(x): 
    print(x) 

pool = ThreadPool(10) 

pool.map(start_it()) 

我知道这是因为输出始终是相同的:

0.1771815430790964 
0.1771815430790964 
0.1771815430790964 
0.1771815430790964 
0.1771815430790964 
0.1771815430790964 
0.1771815430790964 
+1

你确定你的线程实际上是同时运行吗?把一些日志记录放进去。你知道GIL及其对线程代码的影响吗?微型加工可能会更好。 – scytale

+0

多处理有什么区别? –

+0

请详细阅读我以前的评论 – scytale

回答

-1

我认为这种方式可以忠实地平行延伸。我经历了爬行的显着加速。真棒;)

import multiprocessing 
import random 

def worker(): 
    """worker function""" 

    x = random.random()*10 
    x = round(x) 
    while(True): 
     print(x , ' Worker') 

if __name__ == '__main__': 
    jobs = [] 
    for i in range(5): 
     p = multiprocessing.Process(target=worker) 
     jobs.append(p) 
     p.start() 
+0

让我们说它是作为多个流程运行的,真正平行的可能不是。 – lxx

+0

它的确如此。从文档:'过程对象表示在单独的进程中运行的活动'。你可以通过在每个worker中打印os.getpid()来验证,你会看到它。 – csl

+0

不要忘记'加入'你的过程。 – csl

2

,你需要在你运行start_it()的时刻提供pool.map()可迭代

基本上运行您的来电相继。我不知道你用的是什么实现的ThreadPool但你可能需要做一些事情,如:

pool.map(get_urls, list_of_urls) 
+0

我没有url列表,因为每个get_urls()进程都需要一个url数据库的条目 –

+1

很好地适应了我让我们看看 – scytale

0

不离题,但异步IO也是你的问题一个很好的候选人。您可以使用一个名为asyncio的惊人库,它最近已被添加到python 3.4中。对于旧版本,您可以使用trolliusTwisted

0

如果您发布的代码actualy运行时,你不应该做pool.map(start_it()),因为调用之前start_it结果传递给pool.map。相反,您必须通过start_it而没有任何(),如pool.map(start_it)。你可能需要另一个参数(值传递给start_it)。

你可以尝试下面的例子,这似乎适用于我。

import json 
import multiprocessing.pool 
import time 
import urllib2 

def run(no): 
    for n in range(3): 
     f = urllib2.urlopen("http://time.jsontest.com") 
     data = json.loads(f.read()) 
     f.close() 
     print("thread %d: %s" % (no, data)) 
     time.sleep(1) 

pool = multiprocessing.pool.ThreadPool(3) 
pool.map(run, range(3)) 

你也可以使用multiprocess.Process,例如:

import multiprocessing 
import time 
import os 

def run(jobno): 
    for n in range(3): 
     print("job=%d pid=%d" % (jobno, os.getpid())) 
     time.sleep(1) 

jobs = [] 
for n in range(3): 
    p = multiprocessing.Process(target=run, args=[n]) 
    jobs.append(p) 

map(lambda x: x.start(), jobs) 
map(lambda x: x.join(), jobs) 

输出示例:在multiprocessing模块下使用过程而不是线程,这是真正的平行

job=0 pid=18347 
job=1 pid=18348 
job=2 pid=18349 
job=0 pid=18347 
job=2 pid=18349 
job=1 pid=18348 
job=2 pid=18349 
job=0 pid=18347 
job=1 pid=18348 

一切。请注意,可能存在一些问题(与在同一进程下将它们作为线程运行)。

+0

嗨我编辑我的代码,现在它的作品。你在下面看到它。 –

相关问题