网络爬虫案例:爬取百度贴吧某个页面正文中的图片

思路如下:

1.抓取整个网页

2.找到所有图片

3.创建线程池并发下载图片

代码如下: 

public class Crawler {
    //正文图片正则
    static final Pattern PATTERN = Pattern.compile("<img class=\"BDE_Image\" src=\"(.*?)\"");

    // 爬取百度贴吧的图片
    public static void main(String[] args) throws IOException {
        //贴吧地址
        String url = "https://tieba.baidu.com/p/2256306796?red_tag=1781367364";
        // 抓取整个网页
        String html = fetch(url);
        // 创建线程池,并发下载图片
        ExecutorService service = Executors.newFixedThreadPool(8);
        //图片正则匹配网页
        Matcher matcher = PATTERN.matcher(html);
        // 找到每个匹配的图片
        while (matcher.find()) {
            // 获取图片的路径
            String imageURL = matcher.group(1);
            // 提交给线程池进行下载
            service.submit(() -> {
                try {
                    download(imageURL);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
        }
        //关闭线程池
        service.shutdown();
    }

    //抓取网页的html内容
    private static String fetch(String url) throws IOException {
        HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
        StringBuilder sb = new StringBuilder(1024 * 1024);
        try (BufferedReader reader =
                     new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"))
        ) {
            while (true) {
                String line = reader.readLine();
                if (line == null) {
                    break;
                }
                sb.append(line);
            }
        } catch (IOException e) {

        }
        return sb.toString();
    }

    //下载图片
    private static void download(String imageURL) throws IOException {
        HttpURLConnection c = (HttpURLConnection) new URL(imageURL).openConnection();
        // https://imgsa.baidu.com/forum/w%3D580/sign=43e292947c1ed21b79c92eed9d6fddae/6bfab2fb43166d228b3c16f2472309f79052d20a.jpg
        // 图片名
        String image = imageURL.substring(imageURL.lastIndexOf("/") + 1);
        try (
                InputStream in = c.getInputStream();
                OutputStream out = new FileOutputStream("e:\\images\\" + image)
        ) {
            byte[] bytes = new byte[1024 * 1024];
            while (true) {
                int len = in.read(bytes);
                if (len == -1) {
                    break;
                }
                out.write(bytes, 0, len);
            }
        }
    }
}

从以上案例中,可以学到:

1.处理资源关闭的语法
try with resources
try(AutoCloseable 资源 = ...) {
    ...
} catch(Exception e) {

}
// finally块没有了
由编译器帮我们添加以下代码:
finally {
    if(资源 != null) {
        try {
            资源.close();
        } catch (Exception e) {

        }
    }
}


> idea中可以用.twr 快捷键添加这个语法

2.使用组匹配可以一次获取关注的内容
例如,字符串中的图片地址
<img class="样式" src="3.png">
可以使用正则来获取到组1的内容,即()内的内容
<img.*src="(.*)">


 3. 贪婪,非贪婪
<img class="样式" src="3.png"> <img class="样式" src="4.png">

如果使用
<img.*src="(.*)">

匹配后组1结果是:
3.png"> <img class="样式" src="4.png

这是因为默认情况下 *, + 等量词是贪婪的(尽可能匹配更多)
需要改为非贪婪,即在量词后跟? (尽可能匹配更少)
```
<img class="样式" src="(.*?)">
```

4. 可以使用多线程提高下载效率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值