目录
  1. 1. 入门
  2. 2. 编码
  3. 3. 下载一只猫
  4. 4. 更好的选择
    1. 4.1. 安装 Requests
    2. 4.2. 安装 BeautifulSoup4
  5. 5. 爬取豆瓣 Top250 电影排行榜
论一只爬虫的自我修养

入门

网络爬虫,又称网页蜘蛛(WebSpider),非常形象的一个名字。互联网是蛛网,而蜘蛛在网上爬,以获取资源。
百度或谷歌这样的搜索引擎检索到需要的网页,就是靠它们的爬虫在互联网上,对每个关键词进行索引,建立索引数据库。经过复杂的算法排序后,这些结果将按照与搜索关键词相关度的高低依次排。
编写一个搜索引擎,十分困难。但是我们可以从最简单的网络爬虫开始,不断改进。
Python 中提供了 urllib(url+lib) 模块,可以让 Python 接入互联网。

  • URL 的一般格式(带 方括号[] 为可选项)

protocol: // hostname[: port] / path / [;parameters] [?query] # fragemnt

  • URL 由三部分组成:

    • 协议(protocol),常见有 http、https、ftp、file、ed2k
    • 存放资源的服务器的 域名系统(DNS) 主机名或 IP 地址(有时候要包括端口号,各种协议都有默认端口号)
    • 主机资源的具体地址
  • 在 Python3 中,urllib 其实是一个包,它包括了 urllib 和urllib2,统一命名为 urllib。这个包中有四个模块:

    • urllib.request for opening and reading URLs,这是做重要的模块
    • urllib.error containing the exceptions raised by urllib.request
    • urllib.parse for parsing URLs
    • urllib.robotparser for parsing robots.txt files
  • Python 爬取内容是以 utf-8 编码的 bytes 对象(打印字符串前有个 b,表示这是一个 bytes 对象),要还原成 html 代码,需要对其进行解码。

编码

为了解决不同国家不同标准的编码方法,Unicode 编码应运而生。它的做法十分简单:创建一个足够大的编码,将所有国家的编码都加进来,统一标准。
而且,为了能节省空间,Unicode 还创造了很多种实现方式。

  • UTF-8 就是 Unicode 的常见实现方式,是一种可变长编码
  • 简单来说,就是当文本时 ASCII 编码的字符时,用 1 字节存放;而文本是其他 Unicode 字符时,按一定算法转换,每个字符使用 1-3 个字节存放。

下载一只猫

我们可以在 http://placekitten.com 尝试下载一张猫的图片。在这个网址后面附上宽度和高度,就可以得到一只随机的猫。

1
2
3
4
5
6
7
import urllib.request

response = urllib.request.urlopen('http://placekitten.com/200/300')
cat_img = response.read()

with open('cat_200_300.jpg', 'wb') as f:
f.write(cat_img)

执行上面代码,就能在文件夹中看到猫的照片了
其实,urlopen() 的参数可是一个字符串也可以是 Request 对象。如果是一个字符串,会默认被转为 Request 对象再传入。
因此,代码也可以这样写:

1
2
req = urllib.request.Request('http://placekitten.com/200/300')
response = urllib.request.urlopen(req)

urlopen() 实际上返回一个类文件对象,因此用 read() 方法来读取内容,除此之外,文档还告诉我们这个类文件对象还能使用以下三个函数:

  • geturl():返回请求的 url,通常用于判断是否重定向
  • info():返回一个 httplib.HTTPMessage 对象,包含远程服务器返回的头信息
  • getcode():返回 HTTP 状态码

更好的选择

通常情况下,Python 官方提供的“电池”都是最可靠和实用的,除了 urllib。因为,还有一个比 urllib 更好的 HTTP 库——Requests

安装 Requests

与之前安装 EasyGui 一样,使用 pip 命令安装即可

安装 BeautifulSoup4

有了 Requests 模块,就可以用它的 get() 方法从服务器上下载网页。但是下载的是网页源代码,不利于检索数据,因而我们需要一个解析器。
推荐使用 BeautifulSoup4(BS4),这是一个网页解析利器。安装方法也是用 pip 命令安装

爬取豆瓣 Top250 电影排行榜

这是我初中就开始看的排行榜,看的电影基本都在上面找的。虽然有些电影已经很老了,但是经典不会随着时间消去的,建议观看。
使用 Requests 下载这个榜单非常简单:

1
2
3
4
5
6
7
8
9
10
11
import requests
import bs4

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0',
}
res = requests.get('https://movie.douban.com/top250', headers=headers)
soup = bs4.BeautifulSoup(res.text, 'html.parser')
targets = soup.find_all('div', class_='hd')
for each in targets:
print(each.a.span.text)
  • 由于豆瓣有反爬虫机制,我刚开始没加 headers,然后 status_code 一直返回 418,于是百度了一番,加上了 headers,居然就可以了。至于 headers 是什么?我也不知道,计网应该会学的

这些数据是什么来的?看一下 HTML 源代码。

每部电影的标题都位于 <div class=‘hd’>…</div> 的标签中,它的从属关系是 div->a->span
所以先调用 find_all() 方法,找到所有 class=‘hd’ 的 div 标签,然后按从属关系直接取出电影名。
现在我们把所有的数据爬出来吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import requests
import bs4


def open_url(url):
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0',
}
res = requests.get(url, headers=headers)
return res


def find_movies(res):
soup = bs4.BeautifulSoup(res.text, 'html.parser')
# 电影名
movies = []
targets = soup.find_all('div', class_='hd')
for each in targets:
movies.append(each.a.span.text)
# 评分
ranks = []
targets = soup.find_all('span', class_='rating_num')
for each in targets:
ranks.append(' 评分:%s ' % each.text)
# 资料
messages = []
targets = soup.find_all('div', class_='bd')
for each in targets:
try:
messages.append(each.p.text.split('\n')[1].strip() + each.p.text.split('\n')[2].strip())
except:
continue

result = []
length = len(movies)
for i in range(length):
result.append(movies[i] + ranks[i] + messages[i] + '\n')
return result


# 找出一共几个页面
def find_depth(res):
soup = bs4.BeautifulSoup(res.text, 'html.parser')
depth = soup.find('span', class_='next').previous_sibling.previous_sibling.text
return int(depth)


def main():
host = "https://movie.douban.com/top250"
res = open_url(host)
depth = find_depth(res)

result = []
for i in range(depth):
url = host + '/?start=' + str(25*i)
res = open_url(url)
result.append(find_movies(res))

with open('豆瓣Top250电影.txt', 'w', encoding='utf-8') as f:
for each in result:
for i in each:
f.write(i)


if __name__ == '__main__':
main()
文章作者: EasonZzZz
文章链接: http://yoursite.com/2020/02/14/学习/Python学习/论一只爬虫的自我修养/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Nice To Meet U