最近帮朋友写了一个简单的股票采集工具,采集的同花顺股票趋势信息,使用php命令行模式编写。只完成了采集部分功能,将输出的数据复制到execl(或ET)分析,比任何后台都方便。
主要函数只有一个类实现(stock.class.php):
<?php
class StockClass{
public $stockId;
public function __construct($stockId){
$this -> stockId = $stockId;
}
private function getUrl(){
return "http://stockpage.10jqka.com.cn/" . $this -> stockId . "/";
}
private function getPage(){
return file_get_contents($this -> getUrl());
}
//核心,通过正则匹配出 标签名,并将对应的方法的结果替换掉标签占位符
public function getInfo($template){
$html = $this -> getPage();
if( preg_match_all("/\{([^\}]*)\}/", $template, $result) ){
foreach($result[1] as $index => $fun){
$template = str_replace($result[0][$index], $this -> $fun($html), $template);
}
}
return mb_convert_encoding($template, "GBK", "UTF-8"); //Windows的命令提示符编码是GBK
}
private function match($pattern, $html, $itemIndex = 1){
$pattern = '/' . str_replace('/', '\/', $pattern) . '/';
if( preg_match($pattern, $html, $result) ){
return $result[$itemIndex];
}else{
return "-";
}
}
//趋势的规则都一样,合并
private function qushiPattern($name){
return '<div class="txt-aside">' . $name . ':</div>\s*<div class="txt-main">([^<]*)</div>';
}
//支持的标签
private function name($html){
return $this -> match("<title>([^\(<]*)\(", $html, 1);
}
private function score($html){
return $this -> match('<span class="analyze-num">(\d+(\.\d+)?)</span>', $html);
}
private function tips($html){
return $this -> match('<span class="analyze-tips">([^<]*)</span>', $html);
}
private function qushishort($html){
return $this -> match($this -> qushiPattern("短期趋势"), $html);
}
private function qushimiddle($html){
return $this -> match($this -> qushiPattern("中期趋势"), $html);
}
private function qushilong($html){
return $this -> match($this -> qushiPattern("长期趋势"), $html);
}
}
?>
命令提示符中的调用方法如下(stock.php):
<?php
if(count($argv) >= 2){
require("stock.class.php");
$stockId = $argv[1];
$stock = new StockClass($stockId);
$temp = $stockId;
$temp .= " {name}"; //名称
$temp .= " {score}"; //评分
$temp .= " {tips}"; //描述
$temp .= " {qushishort}"; //短期趋势
$temp .= " {qushimiddle}"; //中期趋势
$temp .= " {qushilong}"; //长期趋势
//$temp .= " {zidingyi}"; //自定义,直接在StockClass增加zidingyi方法即可
$temp .= "\n";
echo $stock -> getInfo($temp);
}
?>
直接使用 *\php.exe stock.php 股票代码即可实现调用,每次输入太长的,可以用批处理简化。将下面的代码保存为 stock.cmd。
@XXX\php.exe stock.php %1
运行结果:
这样就完成了单个股票趋势的采集,如果要采集所有的股票信息,可以保存为批处理文件(batch.cmd)
1
@echo off
call stock 000001
call stock 000002
call stock 000003
call stock 000004
call stock 000005
call stock 000006
call stock 000007
call stock 股票代码n...
双击打开即可显示,如果想保存到文件,可以执行 batch.cmd > log.txt,然后将结果复制到 Execl(或ET)即可进行更负责的分析。
前言
这次来做的是通过代码的方式,模拟登录秒拍官网,获取登录用户的信息。
前后端分离
本文的标题是CURL,传统的网站是PHP代码直接渲染项目视图,通过表单提交到控制器直接进行数据操作。
传统模拟登录的方式在页面上找到表单元素,直接进行模拟表单提交。
近两年前端技术趋于完善,实现了前后端分离。
分析页面元素
秒拍官网地址 http://www.miaopai.com/
通过审查元素以及源代码查找,在本页面并没有form标签,由此推断页面是通过js进行提交的。
查找提交地址
由于提交的js代码可能写在了外部的js文件中,直接查找很不方便,所以通过Chrome的调试模式寻找发送的http请求。
注意勾选下图的Preserve log,避免页面跳转的请求记录丢失。
填入手机号密码,在Chrome的Network中查找登录接口请求。
显然,得到登录请求接口 http://www.miaopai.com/cu/login
POSTMAN模拟登录
接口具体信息如下
首先使用postman进行模拟登录测试。
模拟登录毫无压力。
pwd字段经过测试只是简单的md5加密,没有问题。
PHP模拟登录
注意的是,postman自带方法可以直接输出各种语言的代码。
经过整理的PHP代码如下
//手机号
$phone = 13000000000;
//密码
$pwd = md5("password");
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "http://www.miaopai.com/cu/login?phone={$phone}&pwd={$pwd}&checked=false&ph=0",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HEADER=>true,
CURLOPT_HTTPHEADER => array(
"cache-control: no-cache",
// "postman-token: c13c9f1a-fce6-7ec8-4c91-3f13bd233284"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
if ($err) {
echo "cURL Error #:" . $err;
die();
}
//打印header
if (curl_getinfo($curl, CURLINFO_HTTP_CODE) == '200') {
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
}
curl_close($curl);
$body_arr = (json_decode($body,true));
var_dump($body_arr);
获取用户更多数据
我们发现登录接口的返回值中,还存在url字段,拼接美拍网址之后是当前登录用户的个人页面,可以通过正则匹配的方式,得到当前登录的其他信息。
完整代码如下
//手机号
$phone = 13000000000;
//密码
$pwd = md5("password");
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "http://www.miaopai.com/cu/login?phone={$phone}&pwd={$pwd}&checked=false&ph=0",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HEADER=>true,
CURLOPT_HTTPHEADER => array(
"cache-control: no-cache",
// "postman-token: c13c9f1a-fce6-7ec8-4c91-3f13bd233284"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
if ($err) {
echo "cURL Error #:" . $err;
die();
}
//打印header
if (curl_getinfo($curl, CURLINFO_HTTP_CODE) == '200') {
$headerSize = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$header = substr($response, 0, $headerSize);
$body = substr($response, $headerSize);
}
curl_close($curl);
$body_arr = (json_decode($body,true));
//var_dump($body_arr);
//用户个人页面
$url = "http://www.miaopai.com".$body_arr['url'];
//echo $url ;
//获取对应的数据
$http_body = curl(2,$url);
$http_body = preg_replace("/[\t\n\r]+/","",$http_body);
$str = $http_body[0];
//var_dump($str);
//解析
/*
<a title="关注" href="http://www.miaopai.com/u/mob_76195866/relation/follow.htm">5 关注</a>
*/
$reg_follow='/<a title="关注".*?>(.*?)<\/a>/i';
if(preg_match_all($reg_follow, $str, $matches)){
$body_arr['follow_num']= trim(str_replace("关注","",$matches[1][0]));
}
//粉丝
$reg_fans='/<a title="粉丝".*?>(.*?)<\/a>/i';
if(preg_match_all($reg_fans, $str, $matches)){
$body_arr['fans_num'] = trim(str_replace("粉丝","",$matches[1][0]));
}
//视频
$reg_video='/<a title="视频".*?>(.*?)<\/a>/i';
if(preg_match_all($reg_video, $str, $matches)){
$body_arr['video_num'] = strip_tags(trim(str_replace("视频","",$matches[1][0])));
}
//转发
$reg_feded='/<a title="转发".*?>(.*?)<\/a>/i';
if(preg_match_all($reg_feded, $str, $matches)){
$body_arr['fwded_num'] =strip_tags(trim(str_replace("转发","",$matches[1][0])));
}
//赞
$reg_like='/<a title="赞".*?>(.*?)<\/a>/i';
if(preg_match_all($reg_like, $str, $matches)){
$body_arr['like_num'] = strip_tags(trim(str_replace("赞","",$matches[1][0])));
}
var_dump($body_arr);
/**
* curl处理函数
* @param $url
* @param string $method
* @param array $fields
* @param array $headers
* @param bool $auth
* @return array
*/
function curl($me=1,$url, $method='GET',$fields = [], $headers=[],$auth = false){
$url=trim($url);
if($method == "GET"){
$fields_string = http_build_query($fields);
$url=$url."?".$fields_string;
}
$curl = curl_init($url);
curl_setopt ($curl, CURLOPT_CUSTOMREQUEST, $method );
//手机
if($me == 1){
$ua="Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5";
}
//PC
if($me == 2){
$ua=-"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322)";
}
curl_setopt($curl, CURLOPT_USERAGENT, $ua);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_VERBOSE, 1);
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_ENCODING, "");
$header[0] = "Accept: text/html,application/xhtml+xml,application/xml;";
$header[0] .= "q=0.9,image/webp,*/*;q=0.8";
$header[] = "Cache-Control: max-age=0";
$header[] = "Connection: keep-alive";
$header[] = "Keep-Alive: 10";
$header[] = "Accept-Encoding: gzip, deflate, sdch";
$header[] = "Accept-Language: zh-CN,zh;q=0.8,en;q=0.6";
$header[] = "Pragma: "; // browsers keep this blank.
curl_setopt($curl, CURLOPT_HTTPHEADER, array_merge($header,$headers));
if($auth){
curl_setopt($curl, CURLOPT_USERPWD, "$auth");
curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
}
if($fields){
//POST
if($method == "POST"){
$fields_string = http_build_query($fields);
if(count($fields) != 0 ){
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_BINARYTRANSFER, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $fields_string);
}
}else{
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true) ;
}
}
$response = curl_exec($curl);
$header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
$header_string = substr($response, 0, $header_size);
$body = substr($response, $header_size);
$header_rows = explode(PHP_EOL, $header_string);
foreach($header_rows as $key => $value){
$header_rows[$key]=trim($header_rows[$key]);
}
$i=0;
foreach((array)$header_rows as $hr){
$colonpos = strpos($hr, ':');
$key = $colonpos !== false ? substr($hr, 0, $colonpos) : (int)$i++;
$headers[$key] = $colonpos !== false ? trim(substr($hr, $colonpos+1)) : $hr;
}
$j=0;
foreach((array)$headers as $key => $val){
$vals = explode(';', $val);
if(count($vals) >= 2){
unset($headers[$key]);
foreach($vals as $vk => $vv){
$equalpos = strpos($vv, '=');
$vkey = $equalpos !== false ? trim(substr($vv, 0, $equalpos)) : (int)$j++;
$headers[$key][$vkey] = $equalpos !== false ? trim(substr($vv, $equalpos+1)) : $vv;
}
}
}
curl_close($curl);
return array($body, $headers);
}
得到的结果如下
后记
前后端分离是个趋势,web端也变成了无状态通信,通过token进行身份验证。
结果不重要,重在方法和思路
下面我们来看一篇关于php 执行CutyCapt命令网页截图的教程希望这篇文章能够帮助到各位朋友,希望 文章对各位有帮助。用php使用exec执行命令
PS.默认情况下exec函数是禁用的,打开php.ini检查disable_function是否包含这个还是,有就去除
exec('xvfb-run --server-args="-screen 0, 1024x768x24" CutyCapt --url=http://www.111cn.net --out=2.jpg');
这个里一个问题我的的图片只有首屏就好了,所以裁剪图片
yum install ImageMagick
使用convert -crop进行裁剪
convert -crop 1024x768+0+0 2.jpg 22.jpg
使用convert -resize进行图片缩放
convert -resize 15%x15% 22.jpg 22.jpg
目前这个功能已经嵌入到互推博客的网站里了,效果图
PHP分词软件有许多了,如有一个名为PHPAnalysis分词系统类,我们下面一起来看看这个PHPAnalysisP分词系统类的使用方法。PHPAnalysis分词程序使用居于unicode的词库,使用反向匹配模式分词,理论上兼容编码更广泛,并且对utf-8编码尤为方便。 由于PHPAnalysis是无组件的系统,因此速度会比有组件的稍慢,不过在大量分词中,由于边分词边完成词库载入,因此内容越多,反而会觉得速度越 快,这是正常现象。
PHPAnalysis的词库是用一种类似哈希(Hash)的数据结构进行存储的,因此对于比较短的字符串分词,只需要占极小的资源, 比那种一次性载入所有词条的实际性要高得多,并且词库容量大小不会影响分词执行的速度。
PHPAnalysis分词系统是基于字符串匹配的分词方法进行分词的,这种方法又叫做机械分词方法,它是按照一定的策略将待分析的汉字串与 一个“充分大的”机器词典中的词条进行配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。
按照扫描方向的不同,串匹配分词方法可以分为正向匹配 和逆向匹配;按照不同长度优先匹配的情况,可以分为最大(最长)匹配和最小(最短)匹配;按照是否与词性标注过程相结合,又可以分为单纯分词方法和分词与 标注相结合的一体化方法。常用的几种机械分词方法如下:
正向最大匹配法(由左到右的方向)。
逆向最大匹配法(由右到左的方向)。
最少切分(使每一句中切出的词数最小)。
还可以将上述各种方法相互组合,例如,可以将正向最大匹配方法和逆向最大匹配方法结合起来构成双向匹配法。由于汉语单字成词的特点,正向最小匹配和逆向 最小匹配一般很少使用。一般说来,逆向匹配的切分精度略高于正向匹配,遇到的歧义现象也较少。
统计结果表明,单纯使用正向最大匹配的错误率为1/169, 单纯使用逆向最大匹配的错误率为1/245。但这种精度还远远不能满足实际的需要。实际使用的分词系统,都是把机械分词作为一种初分手段,还需通过利用各 种其它的语言信息来进一步提高切分的准确率。
另一种方法是改进扫描方式,称为特征扫描或标志切分,优先在待分析字符串中识别和切分出一些带有明 显特征的词,以这些词作为断点,可将原字符串分为较小的串再来进机械分词,从而减少匹配的错误率。
另一种方法是将分词和词类标注结合起来,利用丰富的词类 信息对分词决策提供帮助,并且在标注过程中又反过来对分词结果进行检验、调整,从而极大地提高切分的准确率。
PHPAnalysis分词先对需要分词的词进行粗分,然后对粗分的短句子进行二次逆向最大匹配法(RMM)的方法进行分词,分词后对分词结果进行优化,然后才得到最终的分词结果。
API文档
成员变量
变量 默认值 描述
$resultType 1 生成的分词结果数据类型
1 为全部
2为词典词汇及单个中日韩简繁字符及英文
3 为词典词汇及英文
这个变量一般用 SetResultType( $rstype ) 这方法进行设置。
$notSplitLen 5 切分句子最短长度
$toLower false 把英文单词全部转小写
$differMax false 使用最大切分模式对二元词进行消岐
$unitWord true 尝试合并单字(即是新词识别)
$differFreq false 使用热门词优先模式进行消岐
成员函数
__construct()
public function __construct($source_charset='utf-8', $target_charset='utf-8', $load_all=true, $source='')
函数说明:构造函数
参数列表:
$source_charset 源字符串编码
$target_charset 目录字符串编码
$load_all 是否完全加载词典(此参数已经作废)
$source 源字符串
如果输入输出都是utf-8,实际上可以不必使用任何参数进行初始化,而是通过 SetSource 方法设置要操作的文本
SetSource()
public function SetSource( $source, $source_charset='utf-8', $target_charset='utf-8' )
函数说明:设置源字符串
参数列表:
$source 源字符串
$source_charset 源字符串编码
$target_charset 目录字符串编码
返回值:bool
StartAnalysis()
public function StartAnalysis($optimize=true)
函数说明:开始执行分词操作
参数列表:
$optimize 分词后是否尝试优化结果
返回值:void
一个基本的分词过程:
$pa = new PhpAnalysis();
$pa->SetSource('需要进行分词的字符串');
//设置分词属性
$pa->resultType = 2;
$pa->differMax = true;
$pa->StartAnalysis();
//获取你想要的结果
$pa->GetFinallyIndex();
SetResultType()
public function SetResultType( $rstype )
函数说明:设置返回结果的类型,实际是对成员变量$resultType的操作
参数 $rstype 值为:
1 为全部
2为 词典词汇及单个中日韩简繁字符及英文
3 为词典词汇及英文
返回值:void
GetFinallyKeywords()
public function GetFinallyKeywords( $num = 10 )
函数说明:获取出现频率最高的指定词条数(通常用于提取文档关键字)
参数列表:
$num = 10 返回词条个数
返回值:用”,”分隔的关键字列表
GetFinallyResult()
public function GetFinallyResult($spword=' ')
函数说明:获得最终分词结果
参数列表:
$spword 词条之间的分隔符
返回值:string
GetSimpleResult()
public function GetSimpleResult()
函数说明:获得粗分结果
返回值:array
GetSimpleResultAll()
public function GetSimpleResultAll()
函数说明:获得包含属性信息的粗分结果
属性(1中文词句、2 ANSI词汇(包括全角),3 ANSI标点符号(包括全角),4数字(包括全角),5 中文标点或无法识别字符)
返回值:array
GetFinallyIndex()
public function GetFinallyIndex()
函数说明:获取hash索引数组
返回值:array(‘word’=>count,…) 按出现频率排序
MakeDict()
public function MakeDict( $source_file, $target_file='' )
函数说明:把文本文件词库编译成词典
参数列表:
$source_file 源文本文件
$target_file 目标文件(如果不指定,则为当前词典)
返回值:void
ExportDict()
public function ExportDict( $targetfile )
函数说明:导出当前词典全部词条为文本文件
参数列表:
$targetfile 目标文件
返回值:void
简单示例
require_once 'phpanalysis2.0/phpanalysis.class.php';
$pa=new PhpAnalysis();
$pa->SetSource("PHPAnalysis分词系统是基于字符串匹配的分词方法进行分词的,这种方法又叫做机械分词方法,它是按照一定的策略将待分析的汉字串与 一个“充分大的”机器词典中的词条进行配,若在词典中找到某个字符串,则匹配成功(识别出一个词)。按照扫描方向的不同,串匹配分词方法可以分为正向匹配 和逆向匹配;按照不同长度优先匹配的情况,可以分为最大(最长)匹配和最小(最短)匹配;按照是否与词性标注过程相结合,又可以分为单纯分词方法和分词与 标注相结合的一体化方法。常用的几种机械分词方法如下: ");
$pa->resultType=2;
$pa->differMax=true;
$pa->StartAnalysis();
$arr=$pa->GetFinallyIndex();
echo "<pre>";
print_r($arr);
echo "</pre>";