使用 进程池Pool 提高爬取数据的速度。
1 # !/usr/bin/python 2 # -*- coding:utf-8 -*- 3 import requests 4 from requests.exceptions import RequestException 5 import re 6 import json 7 from multiprocessing import Pool,Lock 8 9 10 # 获取单页数据信息; 11 def get_one_page(url, headers): 12 try: 13 response = requests.get(url, headers=headers) 14 if response.status_code == 200: 15 return response.text 16 return None 17 except RequestException: 18 return None 19 20 # 使用正则表达式解析数据; 21 def parse_one_page(html): 22 pattern = re.compile('<dd>.*?board-index.*?>(d+)</i>.*?data-src="(.*?)".*?name"><a.*?>' 23 +'(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>.*?integer">' 24 +'(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S) 25 items = re.findall(pattern, html) 26 # 将获取的数据以字典形式返回; 27 for item in items: 28 yield { 29 'index': item[0], 30 'image': item[1], 31 'title': item[2], 32 'actor': item[3].strip()[3:], 33 'time': item[4].strip()[5:], 34 'score': item[5]+item[6] 35 } 36 37 # 将字典转换为字符串保存, 38 def write_to_file(content): 39 lock.acquire() 40 with open('result.txt', 'a', encoding="utf-8") as f: 41 f.write(json.dumps(content, ensure_ascii=False) + " ") 42 f.close() 43 lock.release() 44 45 def init(l): 46 global lock 47 lock = l 48 49 # 传入爬取链接,运行函数; 50 def main(offset): 51 url = "https://maoyan.com/board/4?offset=" + str(offset) 52 headers = { 53 "User-Agent": "Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36" 54 } 55 html = get_one_page(url, headers=headers) 56 for item in parse_one_page(html): 57 write_to_file(item) 58 59 if __name__ == '__main__': 60 # for i in range(10): 61 # main(i*10) 62 # 使用 进程池 提高爬取速度; 63 lock = Lock() 64 Pool = Pool(initializer=init, initargs=(lock,)) 65 Pool.map(main, [i*10 for i in range(10)])
python限定了多进程要调用的函数不能是类方法,需把多进程调用的函数放到类外面,或者变成静态函数。
但静态函数不能被该类的方法调用( self.ProcessWorker 形式),需在外部调用:如 mc = MyClass(), mc.ProcessWorker 或 MyClass().ProcessWorker 。
python 多进程编程中进程池锁共享问题参考博客:https://blog.csdn.net/qq_27292549/article/details/78929296
# 将数组中的每个元素提取出来当作函数的参数,创建一个个进程,放进进程池中;
# 第一个参数是函数,第二个参数是迭代器,将迭代器中的数字作为参数依次传入函数中