/** * 根据配置提取HTML代码块中的字段 * * @param mixed $confs * @param mixed $html * @param mixed $page * @return void * @author seatle <*****@*****.**> * @created time :2016-09-23 17:13 */ public function get_fields($confs, $html, $url, $page) { $fields = array(); foreach ($confs as $conf) { // 当前field抽取到的内容是否是有多项 $repeated = isset($conf['repeated']) && $conf['repeated'] ? true : false; // 当前field抽取到的内容是否必须有值 $required = isset($conf['required']) && $conf['required'] ? true : false; if (empty($conf['name'])) { log::error("The field name is null, please check your \"fields\" and add the name of the field\n"); exit; } $values = array(); // 如果定义抽取规则 if (!empty($conf['selector'])) { // 如果这个field是上一个field的附带连接 if (isset($conf['source_type']) && $conf['source_type'] == 'attached_url') { // 取出上个field的内容作为连接,内容分页是不进队列直接下载网页的 if (!empty($fields[$conf['attached_url']])) { $collect_url = $this->get_complete_url($url, $fields[$conf['attached_url']]); log::info(date("H:i:s") . " Find attached content page: {$url}"); $html = $this->request_url($collect_url); // 在一个attached_url对应的网页下载完成之后调用. 主要用来对下载的网页进行处理. if ($this->on_attached_download_page) { $return = call_user_func($this->on_attached_download_page, $html, $this); if (isset($return)) { $html = $return; } } // 请求获取完分页数据后把连接删除了 unset($fields[$conf['attached_url']]); } } // 没有设置抽取规则的类型 或者 设置为 xpath if (!isset($conf['selector_type']) || $conf['selector_type'] == 'xpath') { // 返回值一定是多项的 $values = $this->get_fields_xpath($html, $conf['selector'], $conf['name']); } elseif ($conf['selector_type'] == 'regex') { $values = $this->get_fields_regex($html, $conf['selector'], $conf['name']); } // field不为空而且存在子配置 if (!empty($values) && !empty($conf['children'])) { $child_values = array(); // 父项抽取到的html作为子项的提取内容 foreach ($values as $html) { // 递归调用本方法,所以多少子项目都支持 $child_value = $this->get_fields($conf['children'], $url, $html, $page); if (!empty($child_value)) { $child_values[] = $child_value; } } // 有子项就存子项的数组,没有就存HTML代码块 if (!empty($child_values)) { $values = $child_values; } } } if (empty($values)) { // 如果值为空而且值设置为必须项,跳出foreach循环 if ($required) { break; } // 避免内容分页时attached_url拼接时候string + array了 $fields[$conf['name']] = ''; //$fields[$conf['name']] = array(); } else { // 不重复抽取则只取第一个元素 $fields[$conf['name']] = $repeated ? $values : $values[0]; } } if (!empty($fields)) { foreach ($fields as $fieldname => $data) { $pattern = "/<img.*?src=[\\'|\"](.*?(?:[\\.gif|\\.jpg|\\.jpeg|\\.png]))[\\'|\"].*?[\\/]?>/i"; // 在抽取到field内容之后调用, 对其中包含的img标签进行回调处理 if ($this->on_handle_img && preg_match($pattern, $data)) { $return = call_user_func($this->on_handle_img, $fieldname, $data); if (!isset($return)) { log::warn("on_handle_img function return value can't be empty\n"); } else { // 有数据才会执行 on_handle_img 方法,所以这里不要被替换没了 $data = $return; } } // 当一个field的内容被抽取到后进行的回调, 在此回调中可以对网页中抽取的内容作进一步处理 if ($this->on_extract_field) { $return = call_user_func($this->on_extract_field, $fieldname, $data, $page, self::$taskid); if (!isset($return)) { log::warn("on_extract_field function return value can't be empty\n"); } else { // 有数据才会执行 on_extract_field 方法,所以这里不要被替换没了 $fields[$fieldname] = $return; } } } } return $fields; }
/** * @param $name 要获取的POST参数名称 * @param bool $required 该参数是否是必须的 * @param string $defaultVal 如果该参数不是必须的,且没有传递的情况下期望的默认值 * @return null|string 返回参数值,或者直接中断http请求向客户端返回错误信息 */ protected function post($name, $required = true, $defaultVal = 'val') { $result = null; if (!empty($_POST)) { $result = $_POST[$name]; } else { if ($required) { $str = '缺少必要的POST参数' . $name . ' | ' . var_dump($_POST); log::warn($str); $this->ret_error($str); } else { $result = $defaultVal; } } return $result; }