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打断程序运行,或直接关闭窗口,程序退出 那如何让窗口不锁定? 方式二 ...
随机推荐
- java第六天
p37 1.java ant详解 练习8 /** * Created by xkfx on 2017/2/26. */ class A { static int i = 47; } public cl ...
- 20145325张梓靖 《Java程序设计》第1周学习总结
20145325张梓靖 <Java程序设计>第1周学习总结 教材学习内容总结 JAVA三大平台:Java SE.Java EE .Java ME Java SE四个组成部分:JVM .JR ...
- 20162314 Experiment 4 - Graph
Experiment report of Besti course:<Program Design & Data Structures> Class: 1623 Student N ...
- 试着用React写项目-利用react-router解决跳转路由等问题(一)
转载请注明出处:王亟亟的大牛之路 继续本周的大方向,继续学习React,昨天把简单的hi all内容呈现出来后,今天研究如何多页面或者实现页面嵌套, 开始今天的内容前老规矩,先安利:https://g ...
- sqlite的bool字段
简直被坑死了, bool字段更新,只能用0或1,才是正确的更新. 否则select出来的字段是错的 本来用true和false更新的,更新之后,使用sqliteexpert查看,更新结果是对的. 但是 ...
- Redis之字符串
Redis 字符串 String 是redis最基本的类型,value 不仅可以是 String,也可以是数字. 使用 Strings 类型,可以完全实现目前 Memcached 的功能,并且效率更高 ...
- python应用-掷骰子模拟-pygal
pygal安装: Linux下: pip install pygal Windows下: python -m pip install pygal 效果如图: # -*- coding: utf-8 - ...
- Python学习札记(二十六) 函数式编程7 修饰器
修饰器 NOTE 1.函数对象有一个__name__属性,可以拿到函数的名字: #!/usr/bin/env python3 def now(): print('2017/2/19') def mai ...
- 2016湘潭邀请赛—Gambling
http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1244 题意:有a个红球,b个绿球,c个黄球,先拿完a个红球一等奖,先拿完b ...
- 二进制文件和ASCII文件有何区别
二进制文件和ASCII文件(即文本文件)的区别,对于和计算机亲近时间尚短的同学是个难题. 1.一个例子:两种100000 有程序: #include<iostream> using nam ...