Java爬虫——WebMagic案例

抓取51Job的招聘信息

一, Scheduler组件

在解析页面的时候,很可能会解析出相同的url地址(例如商品标题和商品图片超链接,而且url一样),如果不进行处理,同样的url会解析处理多次,浪费资源。所以我们需要有一个url去重的功能

WebMagic提供了Scheduler可以帮助我们解决以上问题。

Scheduler是WebMagic中进行URL管理的组件。一般来说,Scheduler包括两个作用

*对待抓取的URL队列进行管理。

*对已抓取的URL进行去重。

WebMagic内置了几个常用的Scheduler。如果你只是在本地执行规模比较小的爬虫,那么基本无需定制Scheduler,但是了解一下已经提供的几个Scheduler还是有意义的

去重部分被单独抽象成了一个接口:DuplicateRemover,从而可以为同一个Scheduler选择不同的去重方式,以适应不同的需要,目前提供了两种去重方式

RedisScheduler是使用Redis的set进行去重,其他的Scheduler(包括未指定的)默认都使用HashSetDuplicateRemover来进行去重

如果要使用BloomFilter,必须要加入以下依赖:

<!--WebMagic对布隆过滤器的支持-->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>16.0</version>
</dependency>

添加布隆过滤器:

    public static void main(String[] args) {
        Spider.create(new JobProcessor())
                .addUrl("https://kuaibao.jd.com/")//添加需要爬取的网页url
                //不添加addPipeline则会将结果输出在控制台
//                .addPipeline(new FilePipeline("C:\\Users\\admin\\Desktop\\result\\"))//将结果保存在文件中
                .thread(5)//设置多线程
                //创建Schedule抽取url,将url保存在内存队列中,并使用布隆过滤器去重,最大去重100000条;如果不设置Schedule,默认采用HashSet去重
                .setScheduler(new QueueScheduler().setDuplicateRemover(new BloomFilterDuplicateRemover(100000)))
                .run();//执行
        //不需要执行打印,不设置输入流的位置,WebMagic默认输出在控制台
    }

三种去重方式

去重就有三种实现方式,那有什么不同呢?

HashSet

使用java中的HashSet不能重复的特点去重。优点是容易理解。使用方便。

缺点:占用内存大,性能较低。

Redis去重

​ 使用Redis的set进行去重。优点是速度快(Redis本身速度就很快),而且去重不会占用爬虫服务器的资源,可以处理更大数据量的数据爬取。

缺点:需要准备Redis服务器,增加开发和使用成本。

布隆过滤器 (BloomFilter) (使用较多)

使用布隆过滤器也可以实现去重。优点是占用的内存要比使用HashSet要小的多,也适合大量数据的去重操作。

缺点:有误判的可能。没有重复可能会判定重复,但是重复数据一定会判定重复。

布隆过滤器 (Bloom Filter)是由Burton Howard Bloom于1970年提出,它是一种space efficient的概率型数据结构,用于判断一个元素是否在集合中。在垃圾邮件过滤的黑白名单方法、爬虫(Crawler)的网址判重模块中等等经常被用到。

哈希表也能用于判断元素是否在集合中,但是布隆过滤器只需要哈希表的1/8或1/4的空间复杂度就能完成同样的问题。布隆过滤器可以插入元素,但不可以删除已有元素。其中的元素越多,误报率越大,但是漏报是不可能的。

3. Pipeline

在WebMagic中,Pileline是抽取结束后,进行处理的部分,它主要用于抽取结果的保存,也可以定制Pileline可以实现一些通用的功能。在这里我们会定制Pipeline实现数据导入到数据库中

Pipeline的接口定义如下:

public interface Pipeline {

    // ResultItems保存了抽取结果,它是一个Map结构,
    // 在page.putField(key,value)中保存的数据,
    //可以通过ResultItems.get(key)获取
    public void process(ResultItems resultItems, Task task);
}

可以看到,Pipeline其实就是将PageProcessor抽取的结果,继续进行了处理的,其实在Pipeline中完成的功能,你基本上也可以直接在PageProcessor实现,那么为什么会有Pipeline?有几个原因:

1.为了模块分离

“页面抽取”和“后处理、持久化”是爬虫的两个阶段,将其分离开来,一个是代码结构比较清晰,另一个是以后也可能将其处理过程分开,分开在独立的线程以至于不同的机器执行。

Pipeline的功能比较固定,更容易做成通用组件

每个页面的抽取方式千变万化,但是后续处理方式则比较固定,例如保存到文件、保存到数据库这种操作,这些对所有页面都是通用的。

在WebMagic里,一个Spider可以有多个Pipeline,使用Spider.addPipeline()即可增加一个Pipeline。这些Pipeline都会得到处理,例如可以使用实现输出结果到控制台,并且保存到文件的目标。

spider.addPipeline(new ConsolePipeline()).addPipeline(new FilePipeline())

2. 环境搭建

建数据表

CREATE Table job_info(
    id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
    company_name VARCHAR(100) DEFAULT NULL COMMENT '公司名称',
    company_addr VARCHAR(200) DEFAULT NULL COMMENT '公司地址',
    company_info TEXT  COMMENT '公司信息',
    job_name VARCHAR(100) DEFAULT NULL COMMENT '职位名称',
    job_addr VARCHAR(100) DEFAULT NULL COMMENT '工作地点',
    job_info TEXT COMMENT "职位信息",
    salary_min int(10) DEFAULT NULL COMMENT '最低薪资',
    salary_max INT(10) DEFAULT NULL COMMENT '最高薪资',
    url VARCHAR(150) DEFAULT NULL COMMENT '招聘信息详情页',
    time VARCHAR(20) DEFAULT NULL COMMENT '职位最新发布时间',
    PRIMARY KEY (id)
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

在pom.xml中添加依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.2.RELEASE</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.ayulong</groupId>
    <artifactId>ayulong-crawler-job</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--SpringMVC-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!--SpringData Jpa-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>

        <!--MySQL连接包-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.11</version>
        </dependency>

        <!--WebMagic核心包-->
        <dependency>
            <groupId>us.codecraft</groupId>
            <artifactId>webmagic-core</artifactId>
            <version>0.7.3</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--WebMagic扩展-->
        <dependency>
            <groupId>us.codecraft</groupId>
            <artifactId>webmagic-extension</artifactId>
            <version>0.7.3</version>
        </dependency>
        <!--WebMagic对布隆过滤器的支持-->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>16.0</version>
        </dependency>

        <!--工具包  stringUtils -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

</project>

加入配置文件

在resources目录下添加application.yml文件

链接数据库

spring:
  # 数据库配置
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://127.0.0.1:3306/crawlerDB?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
    username: 
    password: 
  # jpa配置
  jpa:
    database: MySQL
    show-sql: false

在resources目录下添加log4j.properties文件

log4j.rootLogger=INFO,A1 

log4j.appender.A1=org.apache.log4j.ConsoleAppender
log4j.appender.A1.layout=org.apache.log4j.PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-d{yyyy-MM-dd HH🇲🇲ss,SSS} [%t] [%c]-[%p] %m%n

编写pojo

@Entity
@Data
@ToString
public class JobInfo {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String companyName;
    private String companyAddr;
    private String companyInfo;
    private String jobName;
    private String jobAddr;
    private String jobInfo;
    private Integer salaryMin;
    private Integer salaryMax;
    private String url;
    private String time;

}

编写Dao

package cn.ayulong.job.dao;

import cn.ayulong.job.pojo.JobInfo;
import org.springframework.data.jpa.repository.JpaRepository;

public interface JobInfoDao extends JpaRepository<JobInfo, Long> {
}

编写Service

编写service接口

此处知识 jpa 的查询方式

public interface JobInfoService {

    /**
     * 保存工作信息
     * @param jobInfo
     */
    public void save(JobInfo jobInfo);

    /**
     * 根据条件查询工作信息
     * @param jobInfo
     * @return
     */
    public List<JobInfo> findJobInfo(JobInfo jobInfo);
}

编写service实现类


@Service
public class JobInfoServiceImpl implements JobInfoService {

    @Autowired
    private JobInfoDao jobInfoDao;

    @Override
    @Transactional
    public void save(JobInfo jobInfo) {

        // 根据每条工作信息的url和发布时间查询数据
        JobInfo param = new JobInfo();
        param.setUrl(jobInfo.getUrl());
        param.setTime(jobInfo.getTime());

        // 执行查询
        List<JobInfo> list = this.findJobInfo(param);

        // 判断查询结果是否为空
        if (list.size() == 0) {
            // 如果查询结果为空, 表示招聘信息数据不存在, 或者已经更新了, 需要增或者更新数据库
            this.jobInfoDao.saveAndFlush(jobInfo);
        }

    }

    @Override
    public List<JobInfo> findJobInfo(JobInfo jobInfo) {

        // 设置查询条件
        Example example = Example.of(jobInfo);

        // 执行查询
        List list = this.jobInfoDao.findAll(example);

        return list;
    }
}

创建引导类

@SpringBootApplication
@EnableScheduling // 开启定时任务
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

环境搭建完毕

3. 代码实现

添加工具类MathSalary(计算薪资的工具类,可忽略)

package cn.ayulong.job.task;

// 转换薪资
public class MathSalary {


    /**
     * 获取薪水范围
     *
     * @param salaryStr
     * @return
     */
    public static Integer[] getSalary(String salaryStr) {
        //声明存放薪水范围的数组
        Integer[] salary = new Integer[2];

        //"500/天"
        //0.8-1.2万/月
        //5-8千/月
        //5-6万/年
        String date = salaryStr.substring(salaryStr.length() - 1, salaryStr.length());
        //如果是按天,则直接乘以240进行计算
        if (!"月".equals(date) && !"年".equals(date)) {
            salaryStr = salaryStr.substring(0, salaryStr.length() - 2);
            salary[0] = salary[1] = str2Num(salaryStr, 240);
            return salary;
        }

        String unit = salaryStr.substring(salaryStr.length() - 3, salaryStr.length() - 2);
        String[] salarys = salaryStr.substring(0, salaryStr.length() - 3).split("-");


        salary[0] = mathSalary(date, unit, salarys[0]);
        salary[1] = mathSalary(date, unit, salarys[1]);

        return salary;


    }

    //根据条件计算薪水
    private static Integer mathSalary(String date, String unit, String salaryStr) {
        Integer salary = 0;

        //判断单位是否是万
        if ("万".equals(unit)) {
            //如果是万,薪水乘以10000
            salary = str2Num(salaryStr, 10000);
        } else {
            //否则乘以1000
            salary = str2Num(salaryStr, 1000);
        }

        //判断时间是否是月
        if ("月".equals(date)) {
            //如果是月,薪水乘以12
            salary = str2Num(salary.toString(), 12);
        }

        return salary;
    }


    private static int str2Num(String salaryStr, int num) {
        try {
            // 把字符串转为小数,必须用Number接受,否则会有精度丢失的问题
            Number result = Float.parseFloat(salaryStr) * num;
            return result.intValue();
        } catch (Exception e) {
        }
        return 0;
    }
}

自定义Pipeline存储数据到数据库中

在WebMagic中,Pileline是抽取结束后,进行处理的部分,它主要用于抽取结果的保存,也可以定制Pileline可以实现一些通用的功能。在这里我们会定制Pipeline实现数据导入到数据库中

@Component
public class SpringDatePipeline implements Pipeline {
    @Autowired
    private JobInfoDao jobInfoDao;
     @Override
   public void process(ResultItems resultItems, Task task) {
        //获取封装好的对象
        JobInfo jobInfo = resultItems.get("jobInfo");
        //判断数据的hi否不为空
        if (jobInfo != null){
            //不为空,保存到数据库
            this.jobInfoDao.saveAndFlush(jobInfo);
        }

    }
}

编写主要的爬虫类(核心)

稍微自己修改了一下, 因为 51job 现在的网页和之前相比改了一些, 数据不能直接在网页的元素上拿到, 所以解析数据的方式也得有所变化, 只能想办法解析网页中的js代码, 测试基本没有什么问题

@Component
public class JobProcessor implements PageProcessor {

    // 因为拿不到下一页的链接只好设置一个变量
    private int count = 1;
    private String url = "https://search.51job.com/list/030200,000000,0000,00,9,99,java,2,1.html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=";
    private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-");
    private String today = formatter.format(new Date());
    /**
    *解析页面的方法
    **/
    @Override
    public void process(Page page) {
        // 因为在51招聘的页面中不能直接拿到页面元素, 经分析数据在页面的js中
        // 于是想办法将js对象(json数据)解析出来, 获取到详情页面的链接放到任务队列中
        // 解析页面, 获取script中招聘详情信息
        String dataJs = page.getHtml().css("script").regex(".*SEARCH_RESULT.*").get();
        // 判断获取到的页面是否为空
        if (!StringUtils.isEmpty(dataJs)) {
            System.out.println("开始抓取第" + count++ + "页");
            // 如果不为空, 表示这是列表页
            // 解析拿到json字符串
            dataJs = dataJs.substring(dataJs.indexOf("{"), dataJs.lastIndexOf("}") + 1);
            // 创建json对象
            JSONObject jsonObject = (JSONObject) JSONObject.parse(dataJs);
            // 根据分析拿到放置信息的数组
            JSONArray resArr = jsonObject.getJSONArray("engine_search_result");
            // 判断数组中是否存在数据
            if (resArr.size() > 0) {
                for (int i = 0; i < resArr.size(); i++) {
                    // 获取数组中的每一个对象
                    JSONObject resObj = (JSONObject) resArr.get(i);
                    //把获取到的url地址放到任务队列中
                    page.addTargetRequest(String.valueOf(resObj.get("job_href")));
                }
                // 获取下一页的url
                String bkUrl = "https://search.51job.com/list/030200,000000,0000,00,9,99,java,2," + (count + 1) + ".html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=";
                // 把url放到任务队列中
                page.addTargetRequest(bkUrl);
            } else {
                // 设置变量为初始值
                count = 0;
                // 如果没有数据那么爬虫结束
                return;
            }
        } else {
            // 如果为空, 表示这是招聘详情页, 解析页面, 获取招聘详情信息, 保存数据
            this.saveJobInfo(page);
        }

    }

    // 解析页面, 获取招聘详情信息, 保存数据
    private void saveJobInfo(Page page) {
        // 创建招聘详情对象
        JobInfo jobInfo = new JobInfo();

        // 解析页面
        Html html = page.getHtml();

        // 获取数据, 封装到对象中
        // 拿到有地址和发布时间的那条文字
        String desc = Jsoup.parse(html.css("p.msg.ltype").toString()).text();
        if (desc == null) {
            // 有极少数非51内部网站无法找到
            return;
        }
        // 为了能够找到发布时间截取了字符串
        desc = desc.substring(0, desc.lastIndexOf("发布"));
        // 设置公司名称
        jobInfo.setCompanyName(html.css("div.cn p.cname a", "text").toString().trim());
        // 设置公司地址
        jobInfo.setCompanyAddr(desc.substring(0, desc.indexOf("|")).trim());
        // 设置公司信息
        jobInfo.setCompanyInfo(Jsoup.parse(html.css("div.tmsg").toString()).text());
        // 设置职位名称
        jobInfo.setJobName(html.css("div.cn h1", "text").toString());
        // 设置工作地址
        jobInfo.setJobAddr(html.css("div.bmsg>p.fp", "text").toString());
        // 设置工作信息(要求)
        jobInfo.setJobInfo(Jsoup.parse(html.css("div.job_msg").toString()).text());
        // 设置当前链接
        jobInfo.setUrl(page.getUrl().toString());
        // 获取薪资
        // 有的没有写薪资, 先获取薪资的字符串
        String salaryText = html.css("div.cn strong", "text").toString();
        // 看看是否没有薪资这个字段
        if (!StringUtils.isEmpty(salaryText)) {
            // 使用工具类转换薪资字符串
            Integer[] salary = MathSalary.getSalary(salaryText);
            jobInfo.setSalaryMax(salary[0]);
            jobInfo.setSalaryMin(salary[1]);
        } else {
            // 没有则设为零
            jobInfo.setSalaryMax(0);
            jobInfo.setSalaryMin(0);
        }
        // 获取发布时间
       // 获取发布时间
        String time = desc.substring(desc.lastIndexOf("|") + 3);
        jobInfo.setTime(today + time.trim());
        // 把结果保存起来
        page.putField("jobInfo", jobInfo);
    }

    private Site site = Site.me()
            .setCharset("gbk") // 设置编码 如果乱码还utf-8
            .setTimeOut(10*1000) // 设置超时时间
            .setRetrySleepTime(3000) // 设置重试的间隔时间
            .setRetryTimes(3); // 设置重试的次数

    @Override
    public Site getSite() {
        return site;
    }
    //注入自定义的存储方式
    @Autowired
    private SpringDataPipeline springDataPipeline;

    // initialDelay当任务启动后, 等多久执行方法
    // fixedDelay每隔多久执行方法
    @Scheduled(initialDelay = 1000, fixedDelay = 1000 * 1000)
    public void process() {
        Spider.create(new JobProcessor())
                .addUrl(url)
                // 设置Secheduler
                .setScheduler(new QueueScheduler()
                        // 设置Bloom去重
                        // //QueueScheduler队列保存抓取url。BloomFilterDuplicateRemover布隆过滤器  值根据实际进行设置,最好比预估(数据)值大(越大越占内存)
                        .setDuplicateRemover(new BloomFilterDuplicateRemover(100000)))
                .thread(10)
                // 设置自定义的Pipeline储存数据方式
                .addPipeline(this.springDataPipeline)
                .run();
    }
}

51Job使用爬虫抓取数据,已经开始需要验证是否是认为操作,小趴菜太菜,只学习了这么一点内容,不知道如何反反爬虫

下面是小趴菜的自己写的PageProcessor核心代码

@Component
public class JobProcessor implements PageProcessor {
    //访问的起始url地址
    private int count = 1;
    private String url = "https://search.51job.com/list/030200,000000,0000,00,9,99,java,2,1.html?lang=c&postchannel=0000&workyear=99&cotype=99&degreefrom=99&jobterm=99&companysize=99&ord_field=0&dibiaoid=0&line=&welfare=";
//    private String url = "https://www.liepin.com/zhaopin/?inputFrom=www_index&workYearCode=0&key=java&scene=input&ckId=gr3kkf194u30rv9s38bculwtahg54c6a&dq=";
    private SimpleDateFormat formatter = new SimpleDateFormat("yyyy-");
    private String today = formatter.format(new Date());

    //核心解析页面
    @Override
    public void process(Page page) {
        //解析页面,获取招聘信息的url地址
        List<Selectable> lists = page.getHtml().css("div.j_joblist  div.e sensors_exposure").nodes();//div.j_joblist div.e_icons ick a.el

//      // 判断获取到的页面是否为空
        if (lists.size() == 0){
            //岗位详情页
            this.saveJobInfo(page);
        }else {
            //招聘信息列表页,解析列表的详情页url,放到任务中
            for (Selectable selectable : lists) {
                String jobInfoUrl = selectable.links().toString();
                //将获取到的url,提交到任务队列中
                page.addTargetRequest(jobInfoUrl);
            }
            //获取下一页的url
            String bkUrl = page.getHtml().css("div.p_in li.bk").nodes().get(1).links().toString();
            //添加到任务队列中
            page.addTargetRequest(bkUrl);
        }

    }

    //解析页面,获取招聘的详情信息
    private void saveJobInfo(Page page) {
        //创建 招聘详情对象
        JobInfo jobInfo = new JobInfo();
        Html html = page.getHtml();

        jobInfo.setCompanyName(html.css("div.cn p.cname a","text").toString());
        jobInfo.setCompanyAddr(Jsoup.parse(html.css("div.bmsg").nodes().get(1).toString()).text());
        jobInfo.setCompanyInfo(Jsoup.parse(html.css("div.tmsg").toString()).text());//获取标签内部的文本内容
        jobInfo.setJobInfo(Jsoup.parse(html.css("div.job_msg").toString()).text());
        jobInfo.setJobName(html.css("div.cn h1","text").toString());
        jobInfo.setJobAddr(html.css("div.cn span.lname","text").toString());
//        jobInfo.setSalaryMin();
//        jobInfo.setSalaryMax();
        jobInfo.setUrl(page.getUrl().toString());
//        jobInfo.setTime();
        //把结果保存在Pipeline中
        page.putField("jobInfo",jobInfo);
    }

    private Site site = Site.me()
            .setCharset("utf8")//设置编码
            .setTimeOut(10 * 1000)//设置超时时间
            .setRetryTimes(3)//设置重试次数
            .setRetrySleepTime(3 * 1000);//设置重试时间间隔

    @Override
    public Site getSite() {
        return site;
    }

    @Autowired
    private SpringDatePipeline springDatePipeline;

    //@Scheduled:开启定时任务
    //initialDelay:当任务启动后,等待多久启动方法
    //fixedDelay:每隔多久执行方法
    @Scheduled(initialDelay = 1000,fixedDelay = 100 * 1000)
    public void process(){
        Spider.create(new JobProcessor())//创建一个Spider对象
                .addUrl(url)//添加开始地址
                //设置url去重
                .setScheduler(new QueueScheduler().setDuplicateRemover(new BloomFilterDuplicateRemover(100000)))
                .thread(10)//线程数量设置
                .addPipeline(springDatePipeline)//持久化到数据库
                .run();//运行
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java爬虫是一种通过编写程序来自动化获取网页信息的技术,而爬取百度全科案例则是指使用Java爬虫技术来获取百度搜索引擎中全科相关的信息。 实现这个案例首先要使用Java开发环境编写爬虫程序。程序可通过Java的网络编程技术模拟浏览器发送HTTP请求,然后获取响应的页面内容。在这个案例中,我们可以使用百度搜索全科相关的关键词,如“全科”、“全科课程”等。 首先,我们需要确定爬取的目标网页,即百度搜索结果页。然后,我们可以通过Java的网络编程技术构造URL对象,使用URLConnection建立连接,并发送HTTP请求。可以设置请求头信息,包括User-Agent、Cookie等。接下来,我们可以获取响应的输入流,并使用Java的IO流技术将输入流转化为字符串,获取网页内容。 获取网页内容后,我们可以使用正则表达式或者HTML解析库来提取需要的信息。对于百度搜索结果页,我们可以使用正则表达式或者HTML解析库来提取搜索结果的标题、URL链接等信息。然后,可以将提取到的信息存储到数据库或者文件中,便于后续的数据分析和处理。 值得注意的是,在爬取百度搜索结果页时,应该遵守相关法律法规和百度的爬虫规则,避免对网站造成过大的负担和侵犯他人的合法权益。 总结一下,使用Java爬虫技术实现百度全科案例可以通过模拟浏览器发送HTTP请求,获取百度搜索结果页的HTML内容,并提取需要的信息。这个案例可以帮助我们获取全科相关的信息,并进行后续的数据分析和处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值