使用Jsoup对豆瓣读书进行爬虫

package Spider;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;

public class Spider {
//数据库层,我就不贴代码出来了,每个人数据库不一样,我会在涉及到数据库的地方注释
    DataBaseHelp db = new DataBaseHelp();

    public void run() {
        //调用getTagsStringList()获取标签列表并且对这个链表遍历获取该标签的图书。
        List<String> tagList = getTagsStringList();
        for (int i = 0; i < tagList.size(); i++) {
            //在数据库中插入该标签
            db.selectAndInsertTagId(tagList.get(i));
            //获取该标签的图书
            getBookListbyTag(tagList.get(i));
        }
    }
    //获取标签tag的所有图书
    public List<Book> getBookListbyTag(String tag) {
    //先将该标签插入数据库,并获得标签id
        int tagId = db.selectAndInsertTagId(tag);
        //循环豆瓣的页面,豆瓣在https://www.douban.com/tag/标签/book?strat=起始书本编号  这个页面展示数量为20的书本,利用循环控制起始编号获取该标签的所有书本
        for (int num = 0;; num += 15) {
            try {
            //使用Jsoup连接,需要导入Jsoup包,网上下一个就好了,注意必须设置cookie,要不然多访问几次豆瓣会禁止访问,cookie随便设置一个值,不过最好模仿豆瓣给浏览器返回的。当然也可以实现先从豆瓣得到cookie。
                Document doc = Jsoup
                        .connect(
                                "https://www.douban.com/tag/"
                                        + URLEncoder.encode(tag, "UTF-8")
                                        + "/book")
                        .data("start", Integer.toString(num))
                        .userAgent(
                                "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36")
                        .header("cookie", "bid=\"Q5KWZL7y8g7\";").get();
                Elements bookElements = doc.select("div.book-list > dl");
                //如果当前页已经没有书本了,跳出循环
                if (bookElements.size() < 1)
                    break;
                 System.out.println(bookElements.select("a.title").html());
                for (int i = 0; i < bookElements.size(); i++) {
                    String bookName = bookElements.get(i).select("a.title")
                            .html();
                    String bookDetail = bookElements.get(i).html();
                    String bookRank = bookElements.get(i)
                            .select("span.rating_nums").html();
                    if (!bookRank.equals("")) {
                        Book book = new Book(bookName, bookDetail, bookRank);
                        System.out.println(bookName + bookRank + "tag" + tag+ "num" + num);
                        //将书本数据插入数据库
                        db.insertBook(bookName, bookDetail, bookRank, tagId);
                        //bookList.add(book);
                    }
                }
                //暂停2秒,豆瓣对一定时间内范围有次数限制,2秒是我实验过程中最小的数字了,多了就会403错误,2s间隔大概2小时能读完豆瓣自给标签的50000本书
                Thread.sleep(2000);
            } catch (IOException | InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                //若报错了,则重新读取这个页面
                num-=15;
            }

        }
        //return bookList;
                return  null;
    }
    //该函数实现获取标签List
    public List<String> getTagsStringList() {
        List<String> lis = new ArrayList<String>();
        try {
            //利用Jsoup连接标签列表页面,同样设置cookie
            Document doc = Jsoup
                    .connect("https://book.douban.com/tag/")
                    .header("host", "book.douban.com")
                    .header("accept",
                            "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
                    .header("scheme", "https")
                    .header("version", "HTTP/1.1")
                    .header("path", "/tag/")
                    .header("accept-encoding", "gzip, deflate, sdch")
                    .header("accept-language", "zh-CN,zh;q=0.8")
                    .header("cookie", "bid=\"Q5KWZL7y8g7\";")
                    .header("cache-control", "max-age=0")
                    .userAgent(
                            "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36")
                    .get();

            Elements tag = doc.select("div.article");
            String[] str = tag.select("a.tag").html().split("\n");
            Collections.addAll(lis, str);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return lis;
    }

    public static void main(String[] args) {
        Spider s = new Spider();
        s.run();

    }
}
好的,Spark爬虫的实现一般分为以下几个步骤: 1. 数据采集:通过HTTP请求获取豆瓣音乐网站的音乐信息,可以使用Scala或Python的HTTP库实现。 2. 数据处理:将采集到的HTML页面进行解析,提取所需的音乐信息,可以使用Scala或Python的HTML解析库实现。 3. 数据清洗:对采集到的音乐信息进行清洗和去重,保证数据的正确性和完整性。 4. 数据存储:将清洗后的数据存储到HDFS或其他分布式存储系统中,可以使用Spark的DataFrame API或RDD API实现。 以下是一个Scala实现的豆瓣音乐爬虫示例: ```scala import org.apache.spark.sql.SparkSession import org.jsoup.Jsoup object DoubanMusicCrawler { def main(args: Array[String]): Unit = { val spark = SparkSession.builder().appName("DoubanMusicCrawler").getOrCreate() val sc = spark.sparkContext // 爬取豆瓣音乐Top250的前10页 val urls = (0 to 9).map(i => s"https://music.douban.com/top250?start=${i * 25}") // 采集页面信息并解析 val musicInfos = sc.parallelize(urls) .flatMap(url => { val html = Jsoup.connect(url).get() val items = html.select("div#content div.article table tbody tr") items.map(item => { val name = item.select("td a").text() val artist = item.select("td:nth-child(2)").text() val rating = item.select("td span.rating_num").text().toDouble val commentCount = item.select("td div.star span:nth-child(4)").text().dropRight(3).toInt (name, artist, rating, commentCount) }) }) // 清洗和去重数据 val cleanedMusicInfos = musicInfos.filter(info => info._1.nonEmpty && info._2.nonEmpty) .map(info => (info._1.trim, info._2.trim, info._3, info._4)) .distinct() // 存储数据到HDFS val outputPath = "/user/hadoop/douban_music_top250" cleanedMusicInfos.toDF("name", "artist", "rating", "commentCount") .write.format("parquet").save(outputPath) spark.stop() } } ``` 这个示例爬取豆瓣音乐Top250的前10页,获取每首音乐的名称、艺术家、评分和评论数,并将其存储到HDFS中。您可以根据实际需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值