爬虫日记-使用request lxml openpyxl re 采集豆瓣新书速递 附源码,可运行。


title: 爬虫日记-豆瓣新书速递
tags: [‘requests’,‘python’,‘lxml’,‘openpyxl’]
date: 2021-12-07
categories: “爬虫日记”


环境
window10
python3
使用到的库
re			字符串匹配
openpyxl	表格操作
requests	网络请求
lxml		网页源码解析

源码地址

步骤

写爬虫之前首先要知道我要怎么写一个爬虫,就像如果要把大象塞进冰箱,也同样思考步骤一样。

请添加图片描述

由上图的类比,我们可以有条不紊,步骤清晰的开始写爬虫了。

1 找到数据

首先我们奥找到我们要采集的数据。

1.1 url

这次我们采集的是豆瓣读书的新书榜,也就是 https://book.douban.com/latest 这个网址。设定目标为新书速递10页的全部数据,那第一页的网址我们就已经拿到了,也就是 https://book.douban.com/latest 。

页面拉到最下面,点一下后面一页的页码,进入第二页,发现它的网址发生了一些变化,如下:
请添加图片描述

首页之后的网址多了 ?subcat=全部&p=3,结合首页的url,进行合理的推理猜测:

latest为最新的意思,即新书速递中的新的意思;

subcat大概是 sub catalogue,即子目录,=后边的全部对应着新书速递页面下面的分类:

猜测首页的url也可以用后面的格式写,即首页的url为:

通过测试,首页的确可以通过这样的方式访问得到。

这里实际的网址为:https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=1,中文的全部在url传递时候会需要进行编码,这里不展开。

综上,这10页的url地址为:

```python
url_list = []
for i in range(1,11):
    url_list.append("https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p={0}".format(i))

#    [
#     'https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=1',
#     'https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=2',
#     'https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=3',
#     'https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=4',
#     'https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=5',
#     'https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=6',
#     'https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=7',
#     'https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=8',
#     'https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=9',
#     'https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=10'
# ]
```
1.2 每页具体要拿到的数据

找完了url,接着我们只要搞定其中的一页,那么其他的都一个样子搞就可以了。

网页上显示的元素有:请添加图片描述

书名、书籍信息、评分、评价人数。

同样的,每本书要采集的数据都差不多,只要确定写好一个,其他的书也都一样的方式可以拿到。

重复的事情让程序帮我们去做就行了,我们告诉程序怎么去拿就可以。

2 把数据下载下来

2.1 request 请求获取源码

本次采集的数据实在是网页web上的,通过右键网页空白处,查看网页源码,可以看到一堆网页代码,稍微往下拉会发现刚才看到的数据在源码中同样存在着(废话)
请添加图片描述

所以我们要把网页的源码下载下来。

这里使用pythonrequests 库。

获取源码的程序为:

import requests		# 导包

url = "https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=1"	# 请求url

headers = {
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36',	# 伪造UA
}
response = requests.request("GET", url, headers=headers)	# requests 请求获取源码

print(response.text)	# 打印出来看一看

实际运行结果为:
请添加图片描述
可以看到我们拿到了源码。

2.2 解析源码,获取有用信息

源码已经拿到了,需要的数据也在里面,但是就好像我的1000颗玻璃球放在了一个垃圾场里,我能看得到,也能捡起来,但是好麻烦啊。

因此我们需要想办法让源码变得更条理清晰,便于捡玻璃球

这里用到的是 lxmletree ,将字符串形式的html源码转换为Element对象,之后用xpath进行解析。这里先不做展开,下个爬虫再说。

import re

import requests
from lxml import etree

url = "https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=1"

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36',
}
response = requests.request("GET", url, headers=headers)

print(response.text)
_ = etree.HTML(response.text)
data_list = _.xpath("//li[contains(@class,'media clearfix')]")
for data in data_list:
    print("-" * 100)
    book_name = data.xpath(".//h2/a/text()")[0].strip()
    book_info = data.xpath(".//p[@class='subject-abstract color-gray']/text()")[0].strip()
    score = data.xpath(".//p[@class='clearfix w250']/span[2]/text()")[0].strip()
    score_numbers = data.xpath(".//p[@class='clearfix w250']/span[3]/text()")[0]
    score_numbers = re.findall("\d+",score_numbers)[0]
    print("书名:\t", book_name)
    print("书籍信息:\t", book_info)
    print("评分:\t", score)
    print("评分人数:\t", score_numbers)

运行结果:
请添加图片描述

这样我们就拿到了需要的数据。

3 把数据存起来

只是这样把数据都放在黑框框中展示肯定是不行的,还是要找个办法把采集到的数据存起来,这里选择保存到excel中,使用的模块是openpyxl

3.1 创建新的工作簿获取当前激活的工作表
from openpyxl import Workbook	# 导包

wb = Workbook()				# 创建新的工作簿
ws = wb.active				# 获取当前激活的工作表,默认第一个啦
3.2 写表头,写数据
ws.cell(1,1).value = "书名"
ws.cell(1,2).value = "书籍信息"
ws.cell(1,3).value = "评分"
ws.cell(1,4).value = "评分人数"
for index,data in enumerate(data_list):
    ......
    print("书名:\t", book_name)
    print("书籍信息:\t", book_info)
    print("评分:\t", score)
    print("评分人数:\t", score_numbers)
    ws.cell(2+index,1).value = book_name
    ws.cell(2+index,2).value = book_info
    ws.cell(2+index,3).value = score
    ws.cell(2+index,4).value = score_numbers

3.3 保存表格
import re
from openpyxl import Workbook
import requests
from lxml import etree

url = "https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p=1"

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36',
}
response = requests.request("GET", url, headers=headers)

print(response.text)
_ = etree.HTML(response.text)
wb = Workbook()
ws = wb.active
ws.cell(1,1).value = "书名"
ws.cell(1,2).value = "书籍信息"
ws.cell(1,3).value = "评分"
ws.cell(1,4).value = "评分人数"
data_list = _.xpath("//li[contains(@class,'media clearfix')]")
for index,data in enumerate(data_list):
    print("-" * 100)
    book_name = data.xpath(".//h2/a/text()")[0].strip()
    book_info = data.xpath(".//p[@class='subject-abstract color-gray']/text()")[0].strip()
    score = data.xpath(".//p[@class='clearfix w250']/span[2]/text()")[0].strip()
    score_numbers = data.xpath(".//p[@class='clearfix w250']/span[3]/text()")[0]
    score_numbers = re.findall("\d+",score_numbers)[0]
    print("书名:\t", book_name)
    print("书籍信息:\t", book_info)
    print("评分:\t", score)
    print("评分人数:\t", score_numbers)
    ws.cell(2+index,1).value = book_name
    ws.cell(2+index,2).value = book_info
    ws.cell(2+index,3).value = score
    ws.cell(2+index,4).value = score_numbers

wb.save('./新书速递.xlsx')

执行程序会在当前文件夹下生成新书速递.xlsx文件,文件内容为

在这里插入图片描述

到目前为止,可以拿到第一页我们所需要的信息,但是后面的每一页都要按照这样的方式重新操作一边,这样肯定是太麻烦了,程序到现在能跑,但是还是可以优化一下。

4总结优化

4.1 梳理程序流程

程序整体流程如下

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WbGyftDG-1638839791665)(http://img.codesix.site/20211207004256.png)]

其中,访问网页,保存数据都是多次执行的操作,可以把它写成函数,需要执行的时候调用即可。

4.2 优化

直接上程序

import re
from openpyxl import Workbook
import requests
from lxml import etree


def get_source_code(url):
    """
    获取给定url的网页源码
    :param url: 要去访问的url
    :return:返回该yrl网页源码,字符串形式
    """
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36',
    }
    response = requests.request("GET", url, headers=headers)

    return response.text


def get_info(text):
    """
    从字符串的网页源码中获取所需要的信息
    :param text: 字符串形式的网页源码
    :return: 列表形式的所需要的信息
                [
                [book_name1,book_info1,score1,score_numbers1],
                [book_name2,book_info2,score2,score_numbers2],
                [book_name3,book_info3,score3,score_numbers3],
                ...
                ]
    """
    _ = etree.HTML(text)
    data_list = _.xpath("//li[contains(@class,'media clearfix')]")
    res = []
    for index, data in enumerate(data_list):
        print("-" * 100)
        book_name = data.xpath(".//h2/a/text()")[0].strip()
        book_info = data.xpath(".//p[@class='subject-abstract color-gray']/text()")[0].strip()
        score = data.xpath(".//p[@class='clearfix w250']/span[2]/text()")[0].strip()
        score_numbers = data.xpath(".//p[@class='clearfix w250']/span[3]/text()")[0]
        score_numbers = re.findall("\d+", score_numbers)[0]
        res.append([book_name, book_info, score, score_numbers])
    return res


def write_to_excel(data_list, path="./新书速递.xlsx"):
    """
    将数据写入到同级目录下的execl表格中。
    :param data_list: 要写入的数据
    :param path: 写入的地址,这地方写死,同级目录下
    :return: 输出一个名为 新书速递 的表格文件到本地统计目录下
    """
    wb = Workbook()
    ws = wb.active
    # 写表头
    ws.cell(1, 1).value = "书名"
    ws.cell(1, 2).value = "书籍信息"
    ws.cell(1, 3).value = "评分"
    ws.cell(1, 4).value = "评分人数"
    for index, data in enumerate(data_list):
        ws.cell(2 + index, 1).value = data[0]
        ws.cell(2 + index, 2).value = data[1]
        ws.cell(2 + index, 3).value = data[2]
        ws.cell(2 + index, 4).value = data[3]
    wb.save(path)


if __name__ == '__main__':
    data_list = []
    for i in range(1, 11):
        # 获取网址
        url = "https://book.douban.com/latest?subcat=%E5%85%A8%E9%83%A8&p={0}".format(i)
        # 获取网页源码
        text = get_source_code(url)
        # 获取所需信息,并保存在程序中
        data_list += get_info(text)
    # 写入本地
    write_to_excel(data_list)

写在最后

不管是写些什么,开始写之前一定要做好规划。正所谓磨刀不误砍柴工,不管是思考一下流程,还是确定框架,设计模式,都要清楚自己写的每一行代码到底是干嘛的。

这个爬虫实际上还是存在很多问题的,但是我想用这个爬虫来记录一下整个写程序的思路。如果可以,从最后的图片对照着mian函数开始看,一定要清楚每一行代码究竟是在整个程序中扮演者什么角色,执行哪一步操作。

实力有限,才疏学浅,如有错误,欢迎指正。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值