Python 爬虫之获取某图书网站图书信息 13 万条

举报
xianyuplus 发表于 2021/02/07 23:54:11 2021/02/07
【摘要】 前言先上一波爬取的结果:实战引入类库import requestsfrom bs4 import BeautifulSoupfrom requests.exceptions import RequestExceptionfrom urllib.parse import urlencodeimport pymongoimport numpy as npimport timefrom faker...

前言

先上一波爬取的结果:

实战

引入类库

import requests
from bs4 import BeautifulSoup
from requests.exceptions import RequestException
from urllib.parse import urlencode
import pymongo
import numpy as np
import time
from faker import Faker

分析页面请求

分别请求不同的标签页面,分析请求链接,可以发现如下规律: tag_url = 'https://book.douban.com' + 标签页中a标签括起来的内容 由此,我们可以构建以下代码,以获取标签页面所有标签链接:

# 解析总标签页面,并拼接获得所有标签页页面链接
def splice_tags_indexhtml(html):
    url = 'https://book.douban.com'
    book_tags = []
    tags_url = []
    soup = BeautifulSoup(html, 'lxml')
    tagurl_lists = soup.select('#content > div > div.article > div > div > table > tbody > tr > td > a')
    for tag_url in tagurl_lists:
        # 获取全部标签的a标签内容,并拼接到一起
        book_tags += [tag_url.attrs["href"]]
    for book_tag in book_tags:
        tags_url.append([url + book_tag])
    return tags_url

我们进入单个标签页面,分析图书列表页面,解析我们需要存储的字段

我们通过bs4解析我们需要的字段,如:出版时间,作者/译者,豆瓣评分,售价,评价人数等。


# 解析单个tag页面下单页的信息
def parse_tag_page(html):
    try:
        soup = BeautifulSoup(html,"lxml")
        tag_name = soup.select('title')[0].get_text().strip()
        list_soup = soup.find('ul', {'class''subject-list'})
        if list_soup == None:
            print('获取信息列表失败')
        else:
            for book_info in list_soup.findAll('div', {'class''info'}):
                # 书名
                title = book_info.find('a').get('title').strip()
                # 评价人数
                people_num = book_info.find('span', {'class''pl'}).get_text().strip()
                # 出版信息,作者
                pub = book_info.find('div', {'class''pub'}).get_text().strip()
                pub_list = pub.split('/')
                try:
                    author_info = '作者/译者: ' + '/'.join(pub_list[0:-3])
                except:
                    author_info = '作者/译者: 暂无'
                try:
                    pub_info = '出版信息: ' + '/'.join(pub_list[-3:-1])
                except:
                    pub_info = '出版信息: 暂无'
                try:
                    price_info = '价格: ' + '/'.join(pub_list[-1:])
                except:
                    price_info = '价格: 暂无'
                try:
                    rating_num= book_info.find('span', {'class''rating_nums'}).get_text().strip()
                except:
                    rating_num = '0.0'
                book_data = {
                    'title': title,
                    'people_num': people_num,
                    'author_info': author_info,
                    'pub_info': pub_info,
                    'price_info': price_info,
                    'rating_num': rating_num
                }
                # return book_data
                if book_data:
                    save_to_mongo(book_data,tag_name)
    except:
        print('解析错误')
        return None

到这里,我们已经可以获取到单个tag下单页的图书信息,这个时候我们只需要加入翻页功能就可以实现单个tag下所有图书的信息爬取。

可以看到页面多了start和type两个参数,同时start参数是从0开始并以20的偏移量递增的,我们按照这个规律可以构建一个生成器以生成start参数。

从文章的第一张图,可以看出不同的tag页有不同的数量的图书,那页面数量也不尽相同,这时应该如何构建生成器?

这个时候我们发现所有的tag在第50页之后都请求不出信息了,所以我们只需构建前50页的页面链接即可,第51页显示如下:

# 请求tag下的每个页面
def get_tag_page(tag_url,page):
        formdata = {
            'start': page,
            'type''T'
        }
        url = tag_url[0]+'?'+ urlencode(formdata)
        try:
            reponse = requests.get(url, headers=headers)
            if reponse.status_code == 200:
                return reponse.text
            return None
        except RequestException:
            print('请求列表页错误')
            return None

反反爬

豆瓣的反爬简单粗暴,直接封IP,为了爬虫的健壮,可以使用代理或者随机Header+随机时延的方式,随机时延可以设置为30到40之间,不过这样大大影响了爬取速率,如果需要快速爬取可以采用代理+多线程+随机Header+随机时延这样就能避过反爬又能快速爬取。

#使用Faker库随机生成虚假header
from faker import Faker
fake = Faker()
headers ={'User-Agent':fake.user_agent()}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。