Python_爬虫_多进程

文章未经允许,不可转载

阅读本文需要Python基础,Linux基础。如果你是一名正在学习爬虫的Pythoner,相信本文会很有帮助,:)

写在前面

如果要抓取100个网页,是不需要多进程的,爬取速度不是瓶颈
如果要抓取200万个网页,是不是需要多进程了?

是的!但是多进程是什么呢?
单进程:一个人干一件事,
多进程:多个人干一件事

如果感兴趣,看看博客的另一篇文章高考吧分析,这是在爬取200万个网页后做出的分析

多进程简述

为了讲述的方便,下面的代码用fork来写,请在Linux和Mac 运行,Windows运行不了(建议解决方案:装一个Linux虚拟机

SHOW YOUR CODE

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# -*- coding: utf-8 -*-
__author__ = 'duohappy'

import os

'''
fork函数产生一个子进程

fork函数很特殊,普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,在各自的地址空间返回。父进程在其地址空间返回子进程pid,子进程在其地址空间返回0
'''

ret = os.fork()

# 子进程返回0
if ret == 0:
print('ret =', ret)
# getpid()得到当前进程的pid
print('subprocess pid is', os.getpid())
# getppid()得到父进程的pid
print('subprocess know parent pid is', os.getppid())
# 父进程返回子进程的pid,返回的不是0,所以父进程执行else语句
else:
print('ret =', ret)
print('parent pid is', os.getpid())

用fork做一个小例子

这个例子大部分代码,请参看Python-数据存储

利用fork同时爬取两个网址

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
# -*- coding: utf-8 -*-
__author__ = 'duohappy'

import csv
import os

import requests
from bs4 import BeautifulSoup

url1 = 'http://zhouww.com/'
url2 = 'http://zhouww.com/page/2/'

def get_info_from(url):
result = [] # 保存结果

headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"
}

web_data = requests.get(url, headers=headers)

web_data.encoding = 'utf-8'
content = web_data.text

soup = BeautifulSoup(content, 'lxml')

include_title_url_tags = soup.select('a.post-title-link')

for tag in include_title_url_tags:
# 组成一个结构化的数据
data = {
"url": 'http://zhouww.com' + tag.get('href'),
"title": tag.text
}

result.append(data)

return result

def export_to_csv(result):
with open('./duohappy.csv', 'a', newline='', encoding='utf-8') as f:
field_names = ['url', 'title']
writer = csv.DictWriter(f, field_names)

# 开始写数据
for data in result:
writer.writerow(data)


ret = os.fork()

if ret == 0: # 子进程执行
export_to_csv(get_info_from(url1))
else: # 父进程执行
export_to_csv(get_info_from(url2))

简单点—multiprocessing

是不是有成熟的进程池可以用?

当然有,multiprocessing的Pool就是很好用的进程池

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
# -*- coding: utf-8 -*-
__author__ = 'duohappy'

import csv
from multiprocessing import Pool

import requests
from bs4 import BeautifulSoup

def get_info_from(url):
result = []

headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"
}

web_data = requests.get(url, headers=headers)

web_data.encoding = 'utf-8'
content = web_data.text

soup = BeautifulSoup(content, 'lxml')

include_title_url_tags = soup.select('a.post-title-link')

for tag in include_title_url_tags:
# 组成一个结构化的数据
data = {
"url": 'http://zhouww.com' + tag.get('href'),
"title": tag.text
}

result.append(data)

# 一般的数据存储是使用数据库的,而不是用文本文件
with open('./duohappy.csv', 'a', newline='', encoding='utf-8') as f:
field_names = ['url', 'title']
writer = csv.DictWriter(f, field_names)

# 开始写数据
for data in result:
writer.writerow(data)


if __name__ == '__main__':

all_urls = ['http://zhouww.com/', 'http://zhouww.com/page/2/']

pool = Pool()
pool.map(get_info_from, all_urls)
pool.close()
pool.join()

写在后面

多进程需要的储备知识有点多,不是一篇博文就可以说完的,本文仅仅只是结合爬虫简单唠一唠,:)

欢迎投稿

您的支持将鼓励我继续创作!