python爬虫实战二:豆瓣读书top250爬取

豆瓣读书top250爬虫实战

  • 前言
  • 爬虫
    • 定义下载链接函数
    • 爬取内容的选择
    • 定位方式的选择
    • 数据预处理
  • 后记

前言

本文主要介绍了对豆瓣读书top250的数据爬取与数据预处理,主要运用的库是re,request,Beautifulsoup,lxml。本文侧重于总结我在爬虫时遇到的一些坑,以及我对待这些坑的方法。文末附上了爬取的代码与数据。这是我的第一个爬虫实战:豆瓣电影top250的姊妹版。

爬虫

定义下载链接函数

在下载网页的时候,经常会遇到报错的情况。为了减少不必要的报错,下载的时候可以注意以下三点:

  1. 每次下载之间进行停顿,否则可能会遭到封禁
  2. 添加header,进行伪装,假装自己不是爬虫。不过header的内容好像可以随意取
  3. 添加编码,decode = ‘utf-8’,否则爬取的内容可能是乱码
# 引入库
import re
import pandas as pd
import time
import urllib.request
from lxml.html import fromstring
from bs4 import BeautifulSoup
# 下载链接
def download(url):
    print('Downloading:', url)
    request = urllib.request.Request(url)
    request.add_header('User-agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36') #进行伪装
    resp = urllib.request.urlopen(request)
    html = resp.read().decode('utf-8') #utf-8编码
    time.sleep(3)   #间隔3s,防止被封禁
    return html

爬取内容的选择

我在爬取豆瓣电影时,采用的方式是,下载每一个索引页,然后再下载每个索引页上的全部电影内容。总共有10个索引页,每页上有25个电影信息,这样就要下载 25*10+10=260 个网站。这样做固然可以增加些许的爬取信息,但是很明显的一个弊端就是耗时较久。
python爬虫实战二:豆瓣读书top250爬取_第1张图片

而我在爬取豆瓣读书时,采用的方式是,下载每一个索引页,然后直接提取索引页上的书籍信息(在书名下面)。这样仅需下载10个网页!而且,当我按爬豆瓣电影的老方法,爬取豆瓣读书时,我发现自己很难定位到作者这个信息。这启示我们要灵活选择爬取内容的方式。
python爬虫实战二:豆瓣读书top250爬取_第2张图片

定位方式的选择

第一篇豆瓣电影中提到过爬虫定位有三种方法:

  1. 通过正则表达式定位
  2. 通过Beautifulsoup中find函数定位
  3. 通过lxml中Xpath定位

那么具体该用那种方法呢?我的原则是:简单为上
我个人建议首选Xpath,因为最简单无脑,直接按 F12,然后选中要爬取的内容,右键copy xpath,其次可以使用Beautifulsoup中的find函数定位,不到万不得已,尽量不用正则表达式。
例如读取书名时采用xpath的定位方法,不过这里有两点要注意:

  1. xpath中需要去掉 /tbody
  2. 需要用 .strip() 去掉换行符和空格

python爬虫实战二:豆瓣读书top250爬取_第3张图片

# 待爬取内容
name = []
rate = []
info = []


# 循环爬取每页内容
for k in range(10):
    url = download('https://book.douban.com/top250?start={}'.format(k*25))
    tree = fromstring(url)
    soup = BeautifulSoup(url)
    #找出该页所有书籍信息
    for k in range(25):
        name.append(tree.xpath('//*[@id="content"]/div/div[1]/div/table[{}]/tr/td[2]/div[1]/a/text()'.format(k+1))[0].strip())
        rate.append(soup.find_all('span',{
     'class':'rating_nums'})[k].get_text())
        info.append(soup.find_all('p',{
     'class':'pl'})[k].get_text())
# 拼接
book_data = pd.concat([name_pd, rate_pd, info_pd], axis=1)
book_data.columns=['书名', '评分', '信息']
book_data.head()

数据预处理

接下来将以上读取到的数据进行预处理:

  1. 将变量 信息 分割成 作家,出版社,出版年,定价
  2. 存在两个异常数据,需要手动调整
  3. 用正则表达式提取 出版年中的年份,定价中的数字部分
  4. 过河拆桥,删去 信息 变量

需要注意的是 作家,出版社,出版年,定价 是按位置索引找出来的,但是这里存在两个异常数据,需要自己手动调整:
python爬虫实战二:豆瓣读书top250爬取_第4张图片
python爬虫实战二:豆瓣读书top250爬取_第5张图片

具体代码如下:

# 数据预处理:

# 将信息分割
Info = book_data['信息'].apply(lambda x: x.split('/'))

# 提取信息
book_data['作家'] = Info.apply(lambda x: x[0])
book_data['出版社'] = Info.apply(lambda x: x[-3])
book_data['出版年'] = Info.apply(lambda x: x[-2])
book_data['定价'] = Info.apply(lambda x: x[-1])

# 手动调整
book_data.iloc[9,4] = '群众出版社'
book_data.iloc[9,5] = '1981'
book_data.iloc[184,5] = '1996'
book_data.iloc[184,6] = '0'

#提取年份
f = lambda x: re.search('[0-9]{4,4}', x).group()
book_data['出版年'] = book_data['出版年'].apply(f)

#提取定价
g = lambda x: re.search('([0-9]+\.[0-9]+|[0-9]+)', x).group()
book_data['定价'] = book_data['定价'].apply(g)

book_data = book_data.drop(['信息'], axis =1)

# 输出
outputpath='c:/Users/zxw/Desktop/修身/与自己/数据分析/数据分析/爬虫/豆瓣读书/book.csv' ## 路径需要自己改!
book_data.to_csv(outputpath,sep=',',index=False,header=True,encoding='utf_8_sig')

后记

目前自己对爬虫算是初步了解了,接下来可能会考虑学习 机器学习 的内容,先从 An Introduction to Statistical Learning with R 写起吧

代码及数据集(提取码: disq)

你可能感兴趣的:(爬虫,python,数据分析)