上次项目中用到<<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.x:bs4解析html基础用法

    Python3.x:bs4解析html基础用法 代码: import urllib.request from bs4 import BeautifulSoup import re url = r'ht ...

  2. supervisor初试

    Supervisor (http://supervisord.org) 是一个用 Python 写的进程管理工具,可以很方便的用来启动.重启.关闭进程(不仅仅是 Python 进程).除了对单个进程的 ...

  3. 20145204 《Java程序设计》第6周学习总结

    20145204 <Java程序设计>第6周学习总结 教材学习内容总结 第十章 输入/输出 数据流 I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据 ...

  4. libcurl开源库在Win7 + VS2012环境下编译、配置详解 以及下载文件并显示下载进度 demo(转载)

    转载:http://blog.csdn.net/fengshuiyue/article/details/39530093(基本教程) 转载:https://my.oschina.net/u/14207 ...

  5. 设置VS快捷代码片段

    一.自定义sinppets方式 1.在VS安装路径[D:\vs2013\VC\Snippets\2052\Visual C++]下新建一个snippt文件 2.添加代码 <?xml versio ...

  6. Python3基础 raise + 指定类型异常+异常的解释 产生特定类型异常

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

  7. Ubuntu 14.04 下安装 TFTP 艰辛之路【转】

    本文转载自:https://blog.csdn.net/donglicaiju76152/article/details/76651210 背景 按说在Linux下安装tftp server 很简单, ...

  8. Codeforces Round #394 (Div. 2) C.Dasha and Password(暴力)

    http://codeforces.com/contest/761/problem/C 题意:给出n个串,每个串的初始光标都位于0(列)处,怎样移动光标能够在凑出密码(每个串的光标位置表示一个密码的字 ...

  9. java学习之浅谈多线程2--线程同步

    如果一个共享资源被多个线程同时访问,可能会遭到破坏.举个例子说明这个问题,假设创建并启动100个线程,每个线程都往同一个账户中添加一个便士,代码如下: import java.util.concurr ...

  10. Django怎么获取get请求里面的参数

    获取get请求里面参数的两种方法之三种写法一,当get网址是127.0.0.1:8000/info/?id=20&s_id=30这种类型的网址时 我们在urls的路由的urlpatterns里 ...