Python 爬虫之获取某图书网站图书信息 13 万条
【摘要】 前言先上一波爬取的结果:实战引入类库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)