我的博客

python爬虫入门(requests)

目录
  1. requests基本用法
    1. 安装
    2. 基本使用
  2. 案例
    1. 1、下载蛋蛋网论坛首页,并保存到文件
    2. 2、下载蛋蛋网师大百问板块目录页的前五页,存为5个文件
    3. 3、把师大百问前五页的内容分析成为标题 + url的形式
    4. 4、分布式/多进(线)程改进

使用python3,requests,BeautifulSoup

requests基本用法

requests是python的http请求库。

用于发送http请求,可以用于获取网站的内容(除了文本内容也包括图片,音视频等多媒体内容)

安装

1
pip install requests

基本使用

  1. 发送get请求
  2. 发送post请求
  3. 操作cookie
  4. 创建会话

案例

围绕蛋蛋网开展,蛋蛋网论坛首页,网址是 https://www.oiegg.com/index.php首页不用登录也可以访问,但是部分页面需要登录才能访问。

1、下载蛋蛋网论坛首页,并保存到文件

下载网页的代码

1
2
import requests
response = requests.get('https://www.oiegg.com/index.php')

第一行是导入依赖

第二行已经通过 GET 方法获取到了蛋蛋网的首页的,response变量就是蛋蛋网的服务器返回给我们的”响应对象“

我们可以通过response.text获取响应的内容。比如查看相应的前400个字符 print(response.text[:400])

存文件的代码

1
2
3
f = open('ioegg_index.html', 'w', encoding='utf8')   # 打开文件,使用utf8编码
f.write(response.text) # 写入内容
f.close() # 关闭文件

这个任务就完成了

2、下载蛋蛋网师大百问板块目录页的前五页,存为5个文件

师大百问也不用登录,目录页地址是https://www.oiegg.com/forumdisplay.php?fid=547

如图所示,师大百问的目录一共2000多页,我们如何翻页呢?

可以看到第二页的地址是 https://www.oiegg.com/forumdisplay.php?fid=547&page=2

这个地址比首页多了一个&page=2,这个就是页码的参数,=几就是第几页

1
2
3
4
5
6
7
8
9
10
11
import requests
# base_url就是不带页面的url,后续我们通过它来拼接页码 1,2,3,4.... 就可以得到任意页面的url了
base_url = 'https://www.oiegg.com/forumdisplay.php?fid=547&page='

for i in range(1, 6): # 这个循环产生从 1到 5的序列
target_url = base_url + str(i) # 拼接出目标url
print('get url : ' + target_url)
response = requests.get(target_url)
f = open('shidaibaiwen_page_%i.html' % i, 'w', encoding='utf8')
f.write(response.text)
f.close()

3、把师大百问前五页的内容分析成为标题 + url的形式

结果如下图

这里需要使用到BeautifulSoup,这是一个用于解析HTML(或者是XML)的库。我们使用它从服务器返回的数据中抽取结构化的数据。

4、分布式/多进(线)程改进

首页要明确为什么要使用分布式,分布式适用的场景。

多线程主要是为了提高CPU利用率,实际上单线程爬虫应用的CPU一般比会较低,主要CPU消耗在于数据解析(就是上面第三步),但是解析之前的下载操作是网络操作,网络操作对于CPU的速度是很慢的,所以CPU往往会等待网络IO造成了CPU利用率较低。多线程可以解决这个问题。

举个例子假设单线程下载一个网页要1秒,而CPU解析可能只花了0.1秒,而你的CPU又是4核心,如果想让CPU满负荷工作,理论上应该开启的进/线程数量
$$
(下载一个网页所需时间 \div CPU解析一个页面的时间) \times 核心数
$$
在这个例子里就是40个。那么就是每秒可以下载40个网页,然后CPU4个核心同时工作,在一秒内正好解析完了这40个网页。

当然这里有一个前提就是这个网站的服务器的性能能够满足,每秒下载40个网页。其实很多网站满足不了这么高的效率,而且如果能满足他们也会限制单一用户的请求速度。但是其实并不影响,你为你不会只对一个网站感兴趣,你可以比如同时爬不同的网站,比如蛋蛋网和北邮人等。

graph LR
    线程1 --> queue(任务队列)
    线程2--> queue
    线程3--> queue
    线程4--> queue
    线程5--> queue
    线程6--> queue
    threadx(线程...) --> queue
    线程40--> queue
    queue --> 解析线程1
    queue --> 解析线程2
    queue --> 解析线程3
    queue --> 解析线程4
    解析线程1 -->结果写入硬盘
    解析线程2 -->结果写入硬盘
    解析线程3 -->结果写入硬盘
    解析线程4 -->结果写入硬盘

系统架构图,这是一个使用任务队列的生产者消费者模型。

代码,我们首先对2中的代码进行一些修改,去掉循环而写成用页码做函数的参数,这样可以利用一个函数生成多线程。

1
2
3
4
5
6
7
8
9
10
11
import requests
# base_url就是不带页面的url,后续我们通过它来拼接页码 1,2,3,4.... 就可以得到任意页面的url了
base_url = 'https://www.oiegg.com/forumdisplay.php?fid=547&page='

def get_page(page_index):
target_url = base_url + str(page_index) # 拼接出目标url
print('get url : ' + target_url)
response = requests.get(target_url)
f = open('shidaibaiwen_page_%i.html' % i, 'w', encoding='utf8')
f.write(response.text)
f.close()

多线程部分

1
2
3
4
5
import threading

for i in range(1,6):
t = threading.Thread(target=get_page, args=(i,))
t.start()

这样最简易的多线程爬虫就完成了

评论无需登录,可以匿名,欢迎评论!