0%

杂七杂八

这几天写了两个东西

  1. 公众号文章转换及处理
  2. 定时领券

需求

一直关注品城记,发现它推荐的店铺信息每期都会整理在公众号文章下,大部分格式是正确的(预想的太美好,其实最后也就30%的转换率。人工维护的信息都有偏差)

XX记公众号文章截图

直接用charles抓包,然后使用php进行批量处理。

思路:文件处理、正则匹配、字符处理、简易ORM、小程序云开发

最近京东年货节,一直放大量的券,京东领券对消费者还是比较友好的。不像猫超,只能靠抢,说你火爆你就没办法。

思路:CURL、url参数处理、执行脚本、并行 (这玩意的效果感觉跟js差不多,太菜了我)

公众号文章转换

Step 1

抓包抓到的Responding直接保存为文件(只抓了列表页,其中携带文章URL标题),扫描文件获取文本内容

  • glob($pattern,$flags=0)
    1. 模式匹配文件名 例:*.jpg / *.txt
    2. 特殊的设定 使用 GLOB_BRACE {a,b,c}来匹配 'a','b','c'
    3. 成功返回绝对路径,否则false
  • scandir ($dir,$sort_order,$context)
    1. 完整路径
    2. 排序方式
    3. 返回相对路径
  • readdir(resource $dir_handle)
    1. opendir() 打开的资源参数

Step 2

提取目标格式中的信息。文本数据不完全规范,需要多次处理。一开始想使用正则,但是对于相交的区间,正则并不能处理,后改用explode。使用explode后就需要对数组进行多次处理了,相对麻烦。

  • str_replace(mixed $search,mixed $replace,mixed $subject,int $count = 0)
    1. searchneedle 同义
    2. 如果 replace 的值的个数少于 search 的个数,多余的替换将使用空字符串来进行。
    3. 如果 search 是一个数组而 replace 是一个字符串,那么 search 中每个元素的替换将始终使用这个字符串。
    4. count 如果被指定,它的值将被设置为替换发生的次数
    5. 替换多维数组中的字符串时可用json_encode而不是遍历,效率更高参考php手册中高赞笔记
  • strstr($haystack,$needle,$before)

    如果你仅仅想确定 needle 是否存在于 haystack 中,请使用速度更快、耗费内存更少的 strpos() 函数。

    1. 返回needle之后/之前的字符串
  • substr() / mb_substr($str,$start,$length,$encoding)

    这个太熟悉了。说下mb_substr吧,是按字符的字节长度来截取。

    意思就是utf-8编码下占三个字节的汉字算一个截取长度

  • strip_tags($str,$allowable_tags)

    由于 strip_tags() 无法实际验证 HTML,不完整或者破损标签将导致更多的数据被删除。

    输入 HTML 标签名字如果大于 1023 字节(bytes)将会被认为是无效的,无论 allowable_tags 参数是怎样的。

    1. 从字符串中去除 HTML 和 PHP 标记
    2. 使用可选的第二个参数指定不被去除的字符列表。
    3. htmlspecialchars() - 将特殊字符转换为 HTML 实体
  • addslashes($str)
    1. 使用反斜线引用字符串
    2. 可用于数据库插入时去掉引号,避免插入失败
  • preg_replace_callback($pattern,$callback,$subject)

    1. 执行一个正则表达式搜索并且使用一个回调进行替换
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public static function filter_Emoji($str)
    {
    $str = preg_replace_callback( //执行一个正则表达式搜索并且使用一个回调进行替换
    '/./u',
    function (array $match) {
    return strlen($match[0]) >= 4 ? '' : $match[0];
    },
    $str);
    return $str;
    }
  • preg_match_all($pattern,$subject,$matches,$flag,$offset)

    1. flag 有几个不同的标记值,用于不同的输出

    2. offset 是偏移量,从目标串偏移位置开始匹配,1开始计数

    3. 好奇这个函数为什么不能匹配相交的区间,看了以下的C源码。

      分了三个部分:

      1)regex 2)match 3)error

      用到了挺多的goto (以前写C++打题的时候从来不用switch、goto以及do while,很有意思。)

      如何查找源码呢,php-src 仓库 Cmd+shift+F -> _function(func_name)

    pcre

    此处使用了jit(即时编译)后,速度比不使用快10倍之多,JIT可以决定是否将代码编译,从而提升执行速度

    这篇关于JAVA的JIT编译器讲的很不错

    ​ 除了一堆宏定义与异常处理之外,pcre就是个库。本质上还是C的strcmp()for循环。发现新世界的大门…….

    pcre2_match

关于“此函数可以安全用于二进制对象”的释义

Step 3

PDO写入数据库,需要正确输出,捕获异常等,这个函数涉及较少,实现调用时思路都大同小异吧。

  1. 单例模式复用数据库连接
  2. insert($field) 拆分数组键值对,拼装sql,绑定参数(需要判断参数类型)
  3. exec() 需要数据输出则使用fetch 不需要则返回 bool
  4. 异常捕获

定时领券

Step 1

使用charles 抓取京东的请求,提取url和请求参数,必须拿到cookie。使用代码封装请求,并测试。

  1. CURL系列函数 (不多说,用到直接查就好,其实用composer的扩展包更友好)
  2. urlencode() 看参数中是否会携带引号等字符,使用这个函数转换

Step 2

使用代理ip、多线程跑。

测试的代理ip被拦截的严重,最后也没用上。

  • 检测代理ip有效性 以下代码引用,from 搜索引擎结果,仅提供思路
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
/**
* 检查代理ip信息有效性
*
* @param string $proxy_ip
* @param int $times 执行检查次数
* @return array
*/
function check_proxy_ip_info($proxy_ip = '', $times = 10)
{
$header = array(
// "GET / HTTP/1.1",
// "HOST: www.baidu.com",
"accept: application/json",
"accept-encoding: gzip, deflate",
"accept-language: en-US,en;q=0.8",
"content-type: application/json",
"user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36",
);
$url = 'http://www.baidu.com/';
$result['succeed_times'] = 0; //成功次数
$result['defeat_times'] = 0; //失败次数
$result['total_spen'] = 0; //总用时
for ($i = 0; $i < $times; $i++) {
$s = microtime();
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url); //设置传输的url
curl_setopt($curl, CURLOPT_HTTPHEADER, $header); //发送http报头
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_ENCODING, 'gzip,deflate'); // 解码压缩文件
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); //不验证证SSL书
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false); //不验证SSL证书

if (@$proxy_ip != false) { //使用代理ip
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Client_Ip: ' . mt_rand(0, 255) . '.' . mt_rand(0, 255) . '.' . mt_rand(0, 255) . '.' . mt_rand(0, 255),
));
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'X-Forwarded-For: ' . mt_rand(0, 255) . '.' . mt_rand(0, 255) . '.' . mt_rand(0, 255) . '.' . mt_rand(0, 255),
));
curl_setopt($curl, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
curl_setopt($curl, CURLOPT_PROXY, $proxy_ip);
}

curl_setopt($curl, CURLOPT_COOKIEFILE, dirname(__FILE__) . '/cookie.txt');
curl_setopt($curl, CURLOPT_COOKIEJAR, dirname(__FILE__) . '/cookie.txt');
curl_setopt($curl, CURLOPT_TIMEOUT, 3); // 设置超时限制防止死循环
// $response_header = curl_getinfo($curl); // 获取返回response报头
$content = curl_exec($curl);
if (strstr($content, '百度一下,你就知道')) {
$result['list'][$i]['status'] = 1;
$result['succeed_times'] += 1;
} else {
$result['list'][$i]['status'] = 0;
$result['defeat_times'] += 1;
}
$e = microtime();
$result['total_spen'] += abs($e - $s);
$result['list'][$i]['spen'] = abs($e - $s);
$result['list'][$i]['content'] = json_encode($content, true);
// $result['list'][$i]['response_header'] = $response_header;
}
$result['precent'] = (number_format($result['succeed_times'] / $times, 4) * 100) . '%';
$result['average_spen'] = number_format($result['total_spen'] / $times, 4);
return $result;
}
  • 使用curl_multi_*() 相关函数 并行地处理批处理cURL句柄

    效果如下图:

    coupon_result

参考文章

在文中已全部引用