JAVA实现问财爬虫

通过 RestTemplate 将查询语句申请发送至问财,实现同花顺问财的爬虫获取数据,例子中实现了将爬取的数据写入excel文件并染成红色,可将其改造放入数据库中.

通过测试发现爬虫自动能访问一百多次左右,会被官方识别为爬虫,解决办法为用浏览器打开问财,验证下图形验证码(因为问财nginx是通过识别ip访问的,短期内同一个ip访问太频繁会被识别出来)

爬取的网站地址为 http://www.iwencai.com/customized/chart/get-robot-data ,爬取过程中会发送请求头和消息体,消息头包含session,这部分是分析网站之后,抽取的js保存到本地,到本地进行运行,得到session后保存在请求头里面进行请求。

需要用到的maven依赖
        <!--执行js脚本依赖-->
        <dependency>
            <groupId>org.openjdk.nashorn</groupId>
            <artifactId>nashorn-core</artifactId>
            <version>15.3</version>
        </dependency>
        
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.8.11</version>
        </dependency>
部分java代码
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.swing.DesktopUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.lhk.datasql.util.MyUtil;
import org.apache.poi.ss.usermodel.*;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.web.client.RestTemplate;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import java.io.File;
import java.nio.charset.Charset;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.IntStream;


/**
 * 问财爬虫实现
 */
public class WCTool {

    private static String WC_ROBOT = "http://www.iwencai.com/customized/chart/get-robot-data";
    private static File file = FileUtil.file(MyUtil.DESKTOP_PREFIX + "市场情绪.xlsx");
    private static String[] NumToStr = new String[]{"一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"};
    private static AtomicInteger maxHarden = new AtomicInteger(0);
    private static RestTemplate restTemplate = new RestTemplate();

    public static void main(String[] args) {
        //List dateSubList = MyUtil.getDateSubList("2023-05-30", "2023-06-15");
        //for (DateTime dateTime : dateSubList) {
        //    if (HolidayUtils.isWorkDay(dateTime) && !DateUtil.isWeekend(dateTime)) {
        //        String question = "非ST " + DateUtil.format(dateTime, DatePattern.CHINESE_DATE_PATTERN);
        //        writeExcelSheet1(question, dateTime);
        //        writeExcelSheet2(question, dateTime);
        //    }
        //}
        String question = "非ST 今日";
        writeExcelSheet1(question, DateUtil.date());
        writeExcelSheet2(question, DateUtil.date());
        DesktopUtil.open(file);
        //JSONArray datas = getDatas(question + "1板 概念");
        //Map res = new HashMap<>();
        //for (int i = 0; i < datas.size(); i++) {
        //    String gls = StrUtil.nullToEmpty(datas.get(i, JSONObject.class).get("所属概念", String.class));
        //    for (String s : gls.split(";")) {
        //        res.put(s, res.containsKey(s) ? res.get(s) + 1 : 1);
        //    }
        //}
        //System.out.println(datas);
    }

    private static void writeExcelSheet1(String question, DateTime date) {
        ExcelReader reader = ExcelUtil.getReader(file, "表格");
        List<Object> heads = reader.read().get(0);
        int rowCount = reader.getRowCount();
        reader.close();
        JSONArray datas = getDatas(question + "1板 行业");
        Map<String, Integer> rds = new HashMap<>();
        for (int i = 0; i < datas.size(); i++) {
            for (String s : datas.get(i, JSONObject.class).get("所属同花顺行业", String.class).split("\\-")) {
                rds.put(s, rds.containsKey(s) ? rds.get(s) + 1 : 1);
            }
        }
        Map<String, Object> res = new LinkedHashMap<>(heads.size());
        res.put("日期", DateUtil.format(date, DatePattern.CHINESE_DATE_PATTERN) + ",星期" + NumToStr[DateUtil.dayOfWeek(date) - 2]);
        StringBuffer rsStr = new StringBuffer();
        MapUtil.sortByValue(rds, true).forEach((k, v) -> {
            if (v > 1) {
                rsStr.append(k + "[" + v + "]");
            }
        });
        res.put("当日热点", rsStr);
        maxHarden.set(0);
        IntStream.range(1, 13).forEach(t -> {
            Integer count = getCount(question + t + "板");
            if (count > 0) {
                maxHarden.set(t);
                res.put(NumToStr[t - 1] + "板", count);
            } else {
                res.put(NumToStr[t - 1] + "板", "");
            }
        });
        ExcelWriter writer = ExcelUtil.getWriter(file, "表格");
        writer.setCurrentRow(rowCount);
        writer.write(Arrays.asList(res));
        sheet1CellStyle(writer, rowCount, res);
        writer.close();
    }

    private static void writeExcelSheet2(String question, DateTime date) {
        ExcelReader reader = ExcelUtil.getReader(file, "折线图");
        List<Object> heads = reader.read().get(0);
        int rowCount = reader.getRowCount();
        reader.close();
        Map<String, Object> res = new LinkedHashMap<>(heads.size());
        res.put("日期", DateUtil.format(date, DatePattern.CHINESE_DATE_PATTERN) + ",星期" + NumToStr[DateUtil.dayOfWeek(date) - 2]);
        for (int i = 1; i < heads.size(); i++) {
            String str = String.valueOf(heads.get(i));
            Integer count = getCount(question + " " + str);
            res.put(str, count);
        }
        /**
         * 单独处理最高板
         */
        res.put("最高板", maxHarden.get());
        ExcelWriter writer = ExcelUtil.getWriter(file, "折线图");
        writer.setCurrentRow(rowCount);
        writer.write(Arrays.asList(res));
        sheet2CellStyle(writer, rowCount, heads.size());
        writer.close();
    }

    private static void sheet1CellStyle(ExcelWriter writer, int rowCount, Map<String, Object> map) {
        Font font = writer.getWorkbook().createFont();
        font.setFontName("楷体");
        font.setFontHeightInPoints((short) 11);
        for (int i = 0; i < 2; i++) {
            setCellStyle(writer, i, rowCount, font, IndexedColors.LIGHT_GREEN);
        }
        for (int i = 0; i < 12; i++) {
            String val = MapUtil.getStr(map, NumToStr[i] + "板");
            if (StrUtil.isNotBlank(val)) {
                setCellStyle(writer, i + 2, rowCount, font, IndexedColors.RED1);
            }
        }
    }

    private static void sheet2CellStyle(ExcelWriter writer, int rowCount, int maxCol) {
        Font font = writer.getWorkbook().createFont();
        font.setFontName("楷体");
        font.setFontHeightInPoints((short) 11);
        for (int i = 0; i < maxCol; i++) {
            setCellStyle(writer, i, rowCount, font, IndexedColors.LIGHT_GREEN);
        }
    }

    private static void setCellStyle(ExcelWriter writer, int row, int col, Font font, IndexedColors colors) {
        CellStyle cellStyle = writer.createCellStyle(row, col);
        cellStyle.setFillForegroundColor(colors.getIndex());
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setFont(font);
        cellStyle.setBorderBottom(BorderStyle.THIN);
        cellStyle.setBorderLeft(BorderStyle.THIN);
        cellStyle.setBorderRight(BorderStyle.THIN);
        cellStyle.setBorderTop(BorderStyle.THIN);
        cellStyle.setWrapText(true);
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        cellStyle.setAlignment(HorizontalAlignment.CENTER);
    }

    private static Integer getCount(String question) {
        Integer count = getBodyData(question).get("meta", JSONObject.class)
                .get("extra", JSONObject.class)
                .get("code_count", Integer.class);
        System.out.println(question + "---" + count);
        return count;
    }

    private static JSONArray getDatas(String question) {
        return getBodyData(question).get("datas", JSONArray.class);
    }

    private static JSONObject getBodyData(String question) {
        JSONObject data = null, body = null;
        try {
            Thread.sleep(1000);
            ResponseEntity<String> responseEntity = restTemplate.postForEntity(WC_ROBOT, getHttpEntity(question), String.class);
            body = JSONUtil.parseObj(responseEntity.getBody());
            data = body.get("data", JSONObject.class)
                    .get("answer", JSONArray.class)
                    .get(0, JSONObject.class)
                    .get("txt", JSONArray.class)
                    .get(0, JSONObject.class)
                    .get("content", JSONObject.class)
                    .get("components", JSONArray.class)
                    .get(0, JSONObject.class)
                    .get("data", JSONObject.class);
        } catch (Exception e) {
            System.out.println(body);
            e.printStackTrace();
        }
        return data;
    }

    private static Map<String, Object> queryLoad(String question) {
    	///略
    }

    private static HttpEntity getHttpEntity(String question) {
    	///略
    }

    private static String getCookie() throws Exception {
    	///略
    }
}

Java爬虫实现访问问财数据并处理

运行截图

JAVA实现问财爬虫_第1张图片
JAVA实现问财爬虫_第2张图片
JAVA实现问财爬虫_第3张图片
JAVA实现问财爬虫_第4张图片

JAVA实现问财爬虫_第5张图片

访问次数过多,java会抛出异常,这个时候打开浏览器访问问财,会被警告,这个时候验证下拼图就又可以重新验证。

JAVA实现问财爬虫_第6张图片
Java爬虫实现访问问财数据并处理

以下内容可以忽略

发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】
发文助手会检测您的文章标题、错别字、内容质量,助您提升文章质量。【创作规范】

你可能感兴趣的:(Java基础,java,爬虫,开发语言)