上下文:
我正在做一个机器人来阅读谷歌第一页上的新闻块 结果。我需要200个搜索查询的结果(完全需要 阅读200页)。
为避免被谷歌阻止,必须等待一段时间才能完成下一步 搜索(来自同一个ip)。如果你在每个之间等待30秒 搜索,阅读将需要的200页(200 * 30/60)= 1h40m。
但随着谷歌搜索结果的变化非常快,我需要200个 几乎同时访问页面。所以阅读所有200页 应该只需几分钟。
如果工作分为20个代理(ips),则需要(200/20 * 30/60)= 5米(20个代理同时运行)
我打算通过cli使用pthreads。
问题/怀疑:
Is it possible to run 20 threads simultaneously? Is it advisable to run only a few trheads?
如果我想运行100个线程(使用100个代理)怎么办?
我还有其他选择吗?
修改:
我找到了另一个选项,为此目的使用php curl_multi or the many libraries written over curl_multi。但我想我会坚持使用pthreads。
答案 0 :(得分:3)
有些硬件有超过20个核心,在这种情况下,它是没有脑子的。
如果您的硬件少于20个核心,它仍然不是一个荒谬的线程数量,因为线程的性质意味着他们花费一些时间阻止等待I / O,并且有更多的时间有目的地睡觉这样你就不会对谷歌感到愤怒。
通常情况下,当使用的线程模型是1:1时,就像在PHP中一样,一般来说,安排与核心一样多的线程是一个好主意,这是一个明智的一般规则。 / p>
显然,在您(整个操作系统)之前启动的软件可能已经安排了比核心更多的线程。
最好的情况仍然表示你不能同时执行更多的线程而不是你有可用的核心,这就是一般规则的原因。但是,许多操作系统线程实际上并不需要同时运行,因此这些服务的作者不会遵循相同的规则。
与操作系统启动的那些线程类似,您打算禁止您的线程同时执行,因此您也可以弯曲规则。
TL; DR是的,我认为没关系。
通常,这可能有点傻。
但是因为你计划在请求之间强制线程长时间休眠,所以在这里可能没问题。
您通常不会期望更多线程等同于更多吞吐量。但是,在这种情况下,这意味着您可以更轻松地使用更多传出地址,整体睡眠时间更短。
您的操作系统对允许您创建的线程数有硬性限制,您可能会在100线程的普通硬件上接近这些限制。
TL; DR在这种情况下,我认为没问题。
如果不是您的操作参数;您需要在请求之间休眠,并使用特定接口或代理通过多个地址路由请求,您可以非常轻松地使用非阻塞I / O.
即使给出了参数,你仍然可以使用非阻塞I / O,但它会使编程任务变得比它需要的复杂得多。
在我(可能是偏见)的观点中,你最好使用线程,解决方案会更简单,错误率更低,并且当你在6个月内恢复它时更容易理解(因为谷歌改变了他们的标记或其他)。
使用代理可能被证明是不可靠和缓慢的,如果这是某个应用程序的核心功能,那么考虑获得足够的IP地址,您可以使用特定的接口自行路由这些请求。 cURL,上下文选项和套接字将允许您设置出站地址,这可能更加可靠和快速。
虽然速度不一定是一个问题,但可靠性应该是。将一台机器绑定到20个地址是合理的,将它绑定到100是不太合理的,但如果需要则必须这样。
答案 1 :(得分:0)
为什么不制作单个循环,遍历代理?
这样一次只有一个进程,你也可以过滤掉死代理,但仍然可以获得所需的更新频率。
你可以这样做:
$proxies=array('127.0.0.1','192.168.1.1'); // define proxies
$dead=array(); // here you can store which proxies went dead (slow, not responding, up to you)
$works=array('http://google.com/page1','http://google.com/page2'); // define what you want to do
$run=true; $last=0; $looptime=(5*60); // 5 minutes update
$workid=0; $proxyid=0;
while ($run)
{
if ($workid<sizeof($works))
{ // have something to do ...
$work=$works[$workid]; $workid++; $success=0;
while (($success==0)and($proxyid<sizeof($proxies)))
{
if (!in_array($proxyid,$dead))
{
$proxy=$proxies[$proxyid];
$success=launch_the_proxy($work,$proxy);
if ($success==0) {if (!in_array($proxyid,$dead)) {$dead[]=$proxyid;}}
}
$proxyid++;
}
}
else
{ // restart the work sequence once there's no more work to do and loop time is reached
if (($last+$looptime)<time()) {$last=time(); $workid=0; $proxyid=0;}
}
sleep(1);
}
请注意,这是一个简单的例子,您必须处理细节。您还必须记住,与工作相比,这个代理需要至少相同数量的代理。 (您可以随后根据需要进行调整,但这需要更复杂的方法来确定可以再次使用哪个代理)