Linux下利用Shell使PHP并发采集淘宝产品
上次项目中用到<<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并发采集淘宝产品的更多相关文章
- Linux C程序操作Mysql 调用PHP采集淘宝商品 (转)
还是继续这个项目. 在上一篇Linux下利用Shell使PHP并发采集淘宝产品中,采用shell将对PHP的调用推到后台执行,模拟多线程. 此方法有一致命缺点,只能人工预判每个程序执行时间.如果判断时 ...
- Linux C程序操作Mysql 调用PHP采集淘宝商品
还是继续这个项目. 在上一篇Linux下利用Shell使PHP并发采集淘宝产品中,采用shell将对PHP的调用推到后台执行,模拟多线程. 此方法有一致命缺点,只能人工预判每个程序执行时间.如果判断时 ...
- linux下利用shell脚本和mysqldump热备份和恢复mysql
对mifeng数据库进行每周六3:33完全热备份,并可以完全恢复! 一.先建立备份脚本 #vi /mifengbackup/backup.sh #!bin/bash cd /mifengbackup ...
- linux下利用shell脚本实现添加crontab任务
本来直接用crontab -e 就可以打开vim,输入要执行的任务保存退出就可以添加任务直接启动运行了.但是今天组长说能不能写个shell不用打开vi就能添加到crontab的. 最先想到的是怎么在s ...
- ftp:linux下利用shell脚本添加虚拟用户并赋予权限
首先ftp配置应为虚拟用户登录模式 用户密码文本目录为/etc/vsftpd/vftpuser,代码如下: #!/bin/bash # ];then username=$ password=$ hom ...
- Linux下的shell与make
Linux下的shell与make 一.shell 1.1 什么是shell ● 用户与Linux的接口 ● 命令解释器 ● 支持多用户 ● 支持复杂的编程语言 ● Shell有很多种,如:csh,t ...
- Linux下利用Ret2Libc绕过DEP
Linux下利用Ret2Libc绕过DEP ⑴. 原理分析: 系统库函数通常是不受DEP(关于DEP,可以查看我之前文章的详细介绍)保护的,所以通过将返回地址指向系统函数可以绕过DEP保护,所以可以 ...
- linux下的shell运算(加、减、乘、除)
linux下的shell运算(加.减.乘.除) 标签: linuxshell运算加减乘除 2014-03-12 16:25 15127人阅读 评论(0) 收藏 举报 分类: linux(17) ((i ...
- 【java】 linux下利用nohup后台运行jar文件包程序
Linux 运行jar包命令如下: 方式一: java -jar XXX.jar 特点:当前ssh窗口被锁定,可按CTRL + C打断程序运行,或直接关闭窗口,程序退出 那如何让窗口不锁定? 方式二 ...
随机推荐
- 搭建linux上的Eclipse+PHP编程环境
最近打算学PHP,于是查阅资料搭建了ubuntu(14.04.3)上的PHP IDE环境 一.准备工作(可略) 主要是推荐科大的源和配置源的方法,因为后于步骤使用到了apt,科大的源非常快,并且有个针 ...
- MySQL 学习笔记整理
1. 创建表 CREATE TABLE item( ID INT(6) NOT NULL AUTO_INCREMENT, Name CHAR(32) NOT NULL, Price DECI ...
- linux kernel 卡在提示信息Waiting for root device /dev/mmcblk0p1...处
一.背景 1.1 移植linux-4.14内核的过程中,此时使用的是ext4文件系统,并且将根文件系统存储在sd卡的第一个分区上 1.2 内核打印完Waiting for root device /d ...
- Python学习札记(二十七) 函数式编程8 偏函数
偏函数 NOTE 1.int()函数提供额外的base参数,默认值为10.如果传入base参数,就可以做N进制的转换: #!/usr/bin/env python3 import functools ...
- python 输出时间
import datetime print(datetime.datetime.now().time())
- [java]No qualifying bean of type 解决方法
1.错误原因:注解写错 2.原理如下: 现在的spring早就已经摆脱了之前一堆xml配置文件的情况,都是通过注解配置的方式进行依赖注入了,通常情况下,我们会有一个配置类,然后通过Annotation ...
- @ResponseBody和@ResponseEntity注解
如果需要返回json格式的数据,那么添加该注解就行了@ResponseBody对于ResponseEntity确切的说是ResponseEntity ,如果你即需要返回数据,又需要确定数据的状态,就用 ...
- STL空间配置器那点事
STL简介 STL(Standard Template Library,标准模板库),从根本上说,STL是一些“容器”的集合,这些“容器”有list,vector,set,map等,STL也是算法和其 ...
- hdu4549矩阵快速幂+费马小定理
转移矩阵很容易求就是|0 1|,第一项是|0| |1 1| |1| 然后直接矩阵快速幂,要用到费马小定理 :假如p是质数,且gcd(a,p)=1,那么 a(p-1)≡1(m ...
- javascript中的回调函数
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...