上次项目中用到<<PHP采集淘宝商品>>

此方法有一个缺点,就是执行效率问题.一个商品采集平均需要0.8秒.那10000个商品采集完需要2个半小时.

首先想到的解决办法是并发.

但是PHP不支持并发(这里是指通过PHP命令执行PHP文件,如果通过apache或nginx等做服务器是可以并发的,是并发访问,不能在程序中实现并发).

通过Shell把对php命令推到后台执行,以达到并发的效果.

整体思路:

  1.在Shell中连接数据库,取出需要更新的产品

  2.Shell中对数据进行循环,把商品id,price,url传递给PHP执行,将执行过程推到后台

  3.每循环20条使程序暂停5秒,达到控制并发数的目的

  4.php得到id,price,url参数后,通过URL进行采集,并返回现价

  5.将现价和原数据库中的价格进行比较,如果有变化或下架则更新.

  6.将执行结果写入日志文件.

Shell

#!/bin/sh
#updateprice.sh
j=
currcyline=;
#查询数据库
for i in `/usr/local/bin/mysql -uroot -pshop123 shop -e"SELECT id,price,url FROM s_goods WHERE url!='' AND keyid like 'taobao%' AND is_off_sale=0 ORDER BY id DESC "`
do
if [ $j -gt ]; then
#前3个循环分别为id,price,url这相当于表头,不需要进行操作,所以从第3开始.
line=$(($j%))
case $line in
)
currcyline=$(($currcyline+)) s=$(($currcyline%)) if [ $s -eq ]; then
sleep #每循环20次休息5秒,以此来控制避免产生过多的后台进行,使服务器压力过大或死机.
fi
id=$i;;
)
price=$i;; )
url=$i;
#echo id:${id} price:${price} url:${url} {
#调用php命令执行PHP文件.
re=`/usr/local/bin/php /var/www/9384shop/cron/goodsupdate.php ${id} ${price} "${url}"`
}&
#此&为推到后台执行, 关键
esac fi
j=$(($j+))
done
wait
#等待后台进行执行完成

PHP:

<?php
/*
============================================================================
Name : goodsupdate.php
Author : 风飘无痕
Version :
Copyright : Your copyright notice
Description : Collect taobao goods
============================================================================
*/ //$argv为获取命令中的参数
$s=microtime(1);
$id=$argv[1];
$oldprice=$argv[2];
$price=getPrice($argv[3]);
$t=microtime(1)-$s;
$r=array();
$r[]=date('Y-m-d H:i:s');
$r[]=$id;
$r[]=ceil($t*1000)/1000;
if($price=='soldout'){
$r[]="OutStock";
$con=mysql_connect('localhost','shop','shop123');
mysql_select_db("shop", $con);
mysql_query("UPDATE s_goods SET is_off_sale=1 WHERE id=".$id);
mysql_close($con);
}
elseif($price===false) $r[]= 'FALSE';
elseif($price==$oldprice) $r[]='EQUAL';
else{
$r[]="UPDATE";
$r[]=$oldprice;
$r[]=$price;
$con=mysql_connect('localhost','shop','shop123');
mysql_select_db("shop", $con);
mysql_query("UPDATE s_goods SET price=".$price." WHERE id=".$id);
mysql_close($con);
}
//以日志的形式保存执行过程
$h=fopen('/home/staff/www/9384shop/log/goodsUpdate.log','a+'); fputcsv($h,$r);
fclose($h); function getPrice($url,$time=1){
$des_url='';
$ch = curl_init();
curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0');
curl_setopt($ch, CURLOPT_REFERER,'http://www.tmall.com/');//采集淘宝商品必须设置此项
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);//设置输出方式, 0为自动输出返回的内容, 1为返回输出的内容,但不自动输出.
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); //timeout on connect
curl_setopt($ch, CURLOPT_TIMEOUT, 30); //timeout on response
curl_setopt($ch, CURLOPT_HEADER, 1);//是否输出头信息,0为不输出,非零则输出
curl_setopt($ch, CURLOPT_MAXREDIRS, 10 );
curl_setopt($ch, CURLOPT_URL, $url);
$content = curl_exec($ch);
curl_close($ch);
if(preg_match('/noitem\.htm/',$content)){
return 'soldout';
}elseif(preg_match("/'reservePrice'\s*:\s*'([\d\.]+?)',/",$content,$price)){
$price = (float)$price[1];
}elseif(preg_match('/price:([\d\.]+?),/',$content,$price)){
$price = (float)$price[1];
}
if(!$price){
preg_match('/id=(\d+)+/',$url,$temp);
$url2="http://mdskip.taobao.com/core/initItemDetail.htm?itemId=".$temp[1];
$ch = curl_init();
curl_setopt( $ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Windows; U; Windows NT 5.1; rv:1.7.3) Gecko/20041001 Firefox/0.10.1" );
curl_setopt( $ch, CURLOPT_URL, $url2 );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
curl_setopt( $ch, CURLOPT_ENCODING, "" );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_REFERER, 'http://www.tmall.com' );
curl_setopt( $ch, CURLOPT_AUTOREFERER, true );
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 10 );
curl_setopt( $ch, CURLOPT_TIMEOUT, 10 );
curl_setopt( $ch, CURLOPT_MAXREDIRS, 10 );
$price_content = curl_exec( $ch );
$response = curl_getinfo( $ch );
curl_close ( $ch );
$price_content=json_decode(iconv('gbk','utf-8',preg_replace('/(\d{10,}):/','"${1}":',$price_content)),true);
$priceinfo=$price_content['defaultModel']['itemPriceResultDO']['priceInfo'];
$price=array();
if(is_array($priceinfo)){
foreach ($priceinfo as $v){
$price[]=$v['price'];
if(is_array($v['promotionList'])){
foreach ($v['promotionList'] as $v2){
$price[]=$v2['extraPromPrice']?$v2['extraPromPrice']:$v2['price'];
}
}
if(is_array($v['suggestivePromotionList'])){
foreach ($v['suggestivePromotionList'] as $v2){
$price[]=$v2['extraPromPrice']?$v2['extraPromPrice']:$v2['price'];
}
}
}
}
$price=count($price)>0?min($price):false; }
if($price) return $price;
elseif($time<3) return getPrice($url,$time+1);//如果没有取到价格递归执行,最多执行3次.
else return false;
}

执行结果:

tail - goodsUpdate.log
"2014-03-21 13:45:34",,0.273,EQUAL
"2014-03-21 13:45:35",,5.883,EQUAL
"2014-03-21 13:45:35",,0.914,EQUAL
"2014-03-21 13:45:35",,0.923,EQUAL
"2014-03-21 13:45:35",,0.927,UPDATE,599.00,181.00
"2014-03-21 13:45:35",,0.908,EQUAL
"2014-03-21 13:45:35",,0.93,EQUAL
"2014-03-21 13:45:35",,0.933,EQUAL
"2014-03-21 13:45:35",,0.946,UPDATE,1547.00,1877.00
"2014-03-21 13:45:35",,0.947,EQUAL

此方法比只用PHP更新大大节约了时间,更新2万个商品大约是半小时.但是线程数非常不好控制

Linux下利用Shell使PHP并发采集淘宝产品的更多相关文章

  1. Linux C程序操作Mysql 调用PHP采集淘宝商品 (转)

    还是继续这个项目. 在上一篇Linux下利用Shell使PHP并发采集淘宝产品中,采用shell将对PHP的调用推到后台执行,模拟多线程. 此方法有一致命缺点,只能人工预判每个程序执行时间.如果判断时 ...

  2. Linux C程序操作Mysql 调用PHP采集淘宝商品

    还是继续这个项目. 在上一篇Linux下利用Shell使PHP并发采集淘宝产品中,采用shell将对PHP的调用推到后台执行,模拟多线程. 此方法有一致命缺点,只能人工预判每个程序执行时间.如果判断时 ...

  3. linux下利用shell脚本和mysqldump热备份和恢复mysql

    对mifeng数据库进行每周六3:33完全热备份,并可以完全恢复! 一.先建立备份脚本 #vi /mifengbackup/backup.sh #!bin/bash cd /mifengbackup ...

  4. linux下利用shell脚本实现添加crontab任务

    本来直接用crontab -e 就可以打开vim,输入要执行的任务保存退出就可以添加任务直接启动运行了.但是今天组长说能不能写个shell不用打开vi就能添加到crontab的. 最先想到的是怎么在s ...

  5. ftp:linux下利用shell脚本添加虚拟用户并赋予权限

    首先ftp配置应为虚拟用户登录模式 用户密码文本目录为/etc/vsftpd/vftpuser,代码如下: #!/bin/bash # ];then username=$ password=$ hom ...

  6. Linux下的shell与make

    Linux下的shell与make 一.shell 1.1 什么是shell ● 用户与Linux的接口 ● 命令解释器 ● 支持多用户 ● 支持复杂的编程语言 ● Shell有很多种,如:csh,t ...

  7. Linux下利用Ret2Libc绕过DEP

    Linux下利用Ret2Libc绕过DEP ⑴.  原理分析: 系统库函数通常是不受DEP(关于DEP,可以查看我之前文章的详细介绍)保护的,所以通过将返回地址指向系统函数可以绕过DEP保护,所以可以 ...

  8. linux下的shell运算(加、减、乘、除)

    linux下的shell运算(加.减.乘.除) 标签: linuxshell运算加减乘除 2014-03-12 16:25 15127人阅读 评论(0) 收藏 举报 分类: linux(17) ((i ...

  9. 【java】 linux下利用nohup后台运行jar文件包程序

    Linux 运行jar包命令如下: 方式一: java -jar XXX.jar 特点:当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出 那如何让窗口不锁定? 方式二 ...

随机推荐

  1. Python3基础 print 自带换行

             Python : 3.7.0          OS : Ubuntu 18.04.1 LTS         IDE : PyCharm 2018.2.4       Conda ...

  2. FastCGI介绍及Nginx fastcgi配置优化

    FastCGI介绍 FastCGI是从CGI发展改进而来的.传统CGI接口方式的主要缺点是性能很差,因为每次HTTP服务器遇到动态程序时都需要重新启动脚本解析器来执行解析,然后结果被返回给HTTP服务 ...

  3. [问题解决]win10误删启动项(BCD)(HP电脑亲测,无需启动盘,并非重装系统)

    昨天使用easyBCD软件,开始不太懂,手残把win10的引导删除了,后来发现电脑关机总是变成重启,无奈强制关机.今天重启了一下电脑,发现电脑已经无法打开了,这才明白昨天是误删了win10的BCD. ...

  4. jsoop_封装

    <script> //java.utils.ArrayList() //包(命名空间) /* var java = {}; java.utils = {}; java.utils.Arra ...

  5. POJ 1006 Biorhythnms(中国剩余定理)

    http://poj.org/problem?id=1006 题意: (n+d) % 23 = p ;(n+d) % 28 = e ;(n+d) % 33 = i ; 求最小的n. 思路: 这道题就是 ...

  6. 51Nod 1419 最小公倍数挑战

    http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1419 题意: 思路: 要想最大,肯定去找尽量大的互质的数,如果不是互质的 ...

  7. MaintainableCSS 《可维护性 CSS》 --- 模板篇

    什么是模块(Modules) ? 模块是一个特别的独立单元,可以与其他模块组合以形成更复杂的结构. 在客厅里,我们可以认为电视,沙发和墙艺术是模块.它们聚在一起创造一个可用的房间. 如果我们把其中一个 ...

  8. Java Spring-AOP的概述

    2017-11-08 19:31:23 AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP ...

  9. CSS的三种样式表和优先级

    1.外部样式表当样式需要应用于很多页面时,外部样式表将是理想的选择.在使用外部样式表的情况下,你可以通过改变一个文件来改变整个站点的外观.每个页面使用 <link> 标签链接到样式表. & ...

  10. Android之水波纹点击效果(RippleView)

    Android5.0后各种炫的效果纷纷出来,写这篇博客主要是讲的是按钮点击效果带有的水波纹(波浪式). 当然我写的这个是自定义来实现的,在低版本(5.0一下)也可以实现点击效果.看看效果图: 上图可看 ...