韵搜坊 -- java爬虫抓取数据

三种抓取方式

  1. 直接调用请求接口(最方便,这里使用该方法) HttpClient,OKHttp,RestTemplate,Hutool
  2. 等网页渲染出明文内容后,从前端页面的内容抓取
  3. 有些网站可能是动态请求的,不会一次性加载所有的数据,而是要你点击某个按钮,输入某个验证码才会显示出数据 -> 无头浏览器

数据抓取的流程

  1. 分析数据源(怎么获取)
  2. 拿到数据后怎么处理
  3. 写入数据库等存储

获取文章

离线抓取方式

具体操作

  1. 过滤请求

image.png

  1. 将响应的数据复制到data/passage.json文件中

image.png

  1. 引入Hutool依赖
<!-- https://hutool.cn/docs/index.html#/ -->
<dependency>
  <groupId>cn.hutool</groupId>
  <artifactId>hutool-all</artifactId>
  <version>5.8.16</version>
</dependency>
  1. 查看官方文档

https://hutool.cn/docs/index.html#/
image.png

  1. 编写测试类

获取用于爬虫的数据
image.png
编写测试类

@SpringBootTest
public class CrawlerTest {

    @Resource
    private PostService postService;
    @Test
    void testFetchPassage() {
        //1.获取数据
        String json = "{\"current\":1,\"pageSize\":8,\"sortField\":\"createTime\",\"sortOrder\":\"descend\",\"category\":\"文章\",\"tags\":[],\"reviewStatus\":1}";
        String url = "https://api.code-nav.cn/api/post/search/page/vo";
        String result = HttpRequest.post(url)
        .body(json)
        .execute().body();
        //2.处理数据:json转对象
        Map<String, Object> map = JSONUtil.toBean(result, Map.class);
        JSONObject data = (JSONObject) map.get("data");
        JSONArray records = (JSONArray) data.get("records");
        List<Post> postList = new ArrayList<>();
        for (Object record : records) {
            Post post = new Post();
            JSONObject tempRecord = (JSONObject) record;
            post.setId(0L);
            post.setTitle(tempRecord.getStr("title"));
            post.setContent(tempRecord.getStr("content"));
            //这里将json数组转为列表再转为json字符串,不知道是为了干什么,为什么不直接把json数组转为json字符串呢?
            JSONArray tags = (JSONArray) tempRecord.get("tags");
            List<String> tagList = tags.toList(String.class);
            //            System.out.println(JSONUtil.toJsonStr(tags));
            post.setTags(JSONUtil.toJsonStr(tagList));
            System.out.println(JSONUtil.toJsonStr(tagList));
            post.setUserId(1L);
            postList.add(post);
            //3.写入数据库
            postService.saveBatch(postList);
        }
    }
}

  1. 写入一次性任务
// 取消@Component注释每次项目启动都会执行run任务
//@Component
@Slf4j
public class FetchInitPostList implements CommandLineRunner {

    @Resource
    private PostService postService;


    @Override
    public void run(String... args) {
        //1.获取数据
        String json = "{\"current\":1,\"pageSize\":8,\"sortField\":\"createTime\",\"sortOrder\":\"descend\",\"category\":\"文章\",\"tags\":[],\"reviewStatus\":1}";
        String url = "https://api.code-nav.cn/api/post/search/page/vo";
        String result = HttpRequest.post(url)
                .body(json)
                .execute().body();
        //2.处理数据:json转对象
        Map<String, Object> map = JSONUtil.toBean(result, Map.class);
        JSONObject data = (JSONObject) map.get("data");
        JSONArray records = (JSONArray) data.get("records");
        List<Post> postList = new ArrayList<>();
        for (Object record : records) {
            Post post = new Post();
            JSONObject tempRecord = (JSONObject) record;
            post.setId(0L);
            post.setTitle(tempRecord.getStr("title"));
            post.setContent(tempRecord.getStr("content"));
            //这里将json数组转为列表再转为json字符串,不知道是为了干什么,为什么不直接把json数组转为json字符串呢?
            JSONArray tags = (JSONArray) tempRecord.get("tags");
            List<String> tagList = tags.toList(String.class);
           //JSONUtil.toJsonStr(tags);
            post.setTags(JSONUtil.toJsonStr(tagList));
            post.setUserId(1L);
            postList.add(post);
            //3.写入数据库
            postService.saveBatch(postList);
        }
    }
}

获取用户

每个网站的用户都是自己的,没必要抓取

获取图片

实时抓取:我们自己的网站不存在这些数据,用户要搜的时候,直接从别人的接口(网站)去搜
image.png
jsoup库:获取到HTML文档,然后从中解析出需要的字段

jsoup操作

  1. 导入依赖
<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup -->
<dependency>
  <groupId>org.jsoup</groupId>
  <artifactId>jsoup</artifactId>
  <version>1.15.3</version>
</dependency>
  1. 打开官网 (https://jsoup.org/),获取示例代码
Document doc = Jsoup.connect("https://en.wikipedia.org/").get();
log(doc.title());
Elements newsHeadlines = doc.select("#mp-itn b a");
for (Element headline : newsHeadlines) {
    log("%s\n\t%s", 
        headline.attr("title"), headline.absUrl("href"));
}
  1. 通过在网页前端html界面找对应的css选择器,拿到需要的内容
  2. 测试代码
  //抓取图片
    @Test
    void testFetchPicture() throws IOException {
        int current = 1;
        String url = "https://cn.bing.com/images/search?q=%E5%B0%8F%E9%BB%91%E5%AD%90&form=HDRSC2&first=" + current;
        Document doc = Jsoup.connect(url).get();
        Elements elements = doc.select(".iuscp.isv"); //数组,每个元素是每一张图片
        for (Element element : elements) {
            //取图片地址murl
            String m = element.select(".iusc").attr("m");
            Map<String,Object> map = JSONUtil.toBean(m, Map.class);
            String murl  = (String) map.get("murl");
            //取标题
            String title = element.select(".inflnk").attr("aria-label");
            System.out.println(murl);
            System.out.println(title);

        }
    }
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值