进程
运行中的程序,独立的运行程序,进程是资源的基本最小单位,有独立内存,是并行操作。
多进程创建
from multiprocessing import Process
from datetime import datetime
def func(name):
for i in range(100):
print(i, "===", name)
return name
# 创建进程
p1 = Process(target=func, args=("周杰伦",))
p2 = Process(target=func, args=("李克勤",))
# 执行
p1.start()
p2.start()
同时发生任务,并行。
线程
线程是cpu调度的基本最小单位,cpu调动最小资源,通过线程执行资源,一个进程可以拿着资源开若干个线程,不同线程之间交替执行。
4个线程同时进行
from threading import Thread
# 创建任务
def func(name):
for i in range(10000):
print(i, "===", name)
# 创建线程
t1 = Thread(target=func, args=("周杰伦",))
t2 = Thread(target=func, args=("李克勤",))
t3 = Thread(target=func, args=("那英",))
t4 = Thread(target=func, args=("你好",))
# 执行
t1.start()
t2.start()
t3.start()
t4.start()
面向对象多线程程序
继thread并重写Thread的run方法
from threading import Thread
class MyThread(Thread):
def __init__(self, name):
# 继承参数
super(MyThread, self).__init__()
self.name = name
# 重写run方法
def run(self):
for i in range(10000):
print(i, "===", self.name)
# 创建线程
t1 = MyThread("周杰伦")
t2 = MyThread("李克勤")
t3 = MyThread("那英")
t4 = MyThread("你好")
# 执行
t1.start()
t2.start()
t3.start()
t4.start()
线程池
线程是不能随便创建的,所以需要控制线程数量,线程池可以完成这项工作
无返回
from concurrent.futures import ThreadPoolExecutor
# 创建任务
def func(name):
for i in range(10000):
print(i, "===", name)
# 创建线程池
with ThreadPoolExecutor(10) as t:
for i in range(10):
t.submit(func, "周杰伦"+'=='+str(i))
有返回值
- 方法1
from concurrent.futures import ThreadPoolExecutor
# 创建任务
def func(name):
print(i, "===", name)
return name
# 创建线程池 并获取返回值
# add_done_callback 任务完成之后立即执行
with ThreadPoolExecutor(10) as t:
t.submit(func, "周杰伦").add_done_callback(lambda res: print(res.result()))
t.submit(func, "李克勤").add_done_callback(lambda res: print(res.result()))
t.submit(func, "那英").add_done_callback(lambda res: print(res.result()))
- 方法2
from concurrent.futures import ThreadPoolExecutor
# 创建任务
def func(name):
print(i, "===", name)
return name
# 创建线程池 并获取返回值
# add_done_callback 任务完成之后立即执行
with ThreadPoolExecutor(10) as t:
result = t.map(func, ["周杰伦", "李克勤", "那英"])
print(list(result))
何时使用多线程,何时使用多进程
多线程:任务相对统一,互相特别相似
多进程:多个任务相互独立,很少有交集
比如:免费ip池
- 1、从免费网站抓取代理ip
- 2、验证ip是否可用
- 3、准备对外的接口
财 务 部 政 策 实战
# 整合版
import json
import os
import re
import time
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime, timedelta
from multiprocessing import Process, Queue
from urllib.parse import urljoin
import numpy as np
import pandas as pd
import requests
from pyquery import PyQuery
head = {
"User-Agent": np.random.choice(
[
"Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36",
"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.0 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2226.0 Safari/537.36",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; chromeframe/13.0.782.215)",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; chromeframe/11.0.696.57)",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) chromeframe/10.0.648.205",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/4.0; GTB7.4; InfoPath.1; SV1; .NET CLR 2.8.52393; WOW64; en-US)",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; chromeframe/11.0.696.57)",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/4.0; GTB7.4; InfoPath.3; SV1; .NET CLR 3.1.76908; WOW64; en-US)",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/7046A194A",
"Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10A5355d Safari/8536.25",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_8) AppleWebKit/537.13+ (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10",
"Mozilla/5.0 (iPad; CPU OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko ) Version/5.1 Mobile/9B176 Safari/7534.48.3",
]
)
}
def get_today_and_lastday():
t = datetime.now()
oneday = timedelta(days=1)
yesterday = t - oneday
return datetime(year=t.year, month=t.month, day=t.day), datetime(
year=yesterday.year, month=yesterday.month, day=yesterday.day
)
## 1、抓取信息网页
def get_li_list(url, end_time, queue, page=0):
if page != 0:
crawl_url = url + "_%s" % page + ".htm"
else:
crawl_url = url + ".htm"
response = requests.get(crawl_url, headers=head)
response.encoding = "utf-8"
pq = PyQuery(response.text)
li_info_list = [
[urljoin(crawl_url, i("a").attr("href")), i("a").text(), i("span").text()]
for i in list(pq("ul.xwfb_listbox > li").items())
]
# 获取当页最早文章发布时间
publish_time = datetime.strptime(li_info_list[-1][-1], "%Y-%m-%d")
# 如果时间时间小于截至时间,停止
if publish_time < end_time:
return li_info_list
# 否则翻页,递归执行
page += 1
li_info_list += get_li_list(url, end_time, queue, page)
for i in li_info_list:
if (
datetime.strptime(i[-1], "%Y-%m-%d") >= end_time
and datetime.strptime(i[-1], "%Y-%m-%d") < begin_time
):
queue.put(i)
return li_info_list
## 多线程作业
def get_url(q, end_time):
url_list = [
"https://www.mof.gov.cn/zhengwuxinxi/caizhengxinwen/index",
"https://www.mof.gov.cn/zhengwuxinxi/zhengcefabu/index",
"https://www.mof.gov.cn/zhengwuxinxi/zhengcejiedu/index",
]
with ThreadPoolExecutor(num_executor) as t:
for url in url_list:
t.submit(get_li_list, url, end_time, q, page=0)
# 第二步多线程抓取网页信息
def insert_db_data(data):
response = requests.get(data[0], headers=head)
response.encoding = "utf-8"
pq = PyQuery(response.text)
db_insert_data.append(
[
# crawl_time 爬取时间
datetime.now(),
# publish_time 发布时间
datetime.strptime(data[-1], "%Y-%m-%d"),
# 原始网址
data[0],
# 网站模块
pq("div.dangqian").text().split(">")[-1],
# 标题
pq("div.box_content > h2.title_con").text().replace("\n", ""),
# 作者或来源
"中华人民共和国财政部",
# 文章内容
pq("div.TRS_Editor >p").text(),
# 附件 存储附件地址 media/app03/data/
"",
]
)
# (pq("div.box_content > h2.title_con").text(), ">>>>>", "插入队列") 可打印
def get_url_info(
q,
):
with ThreadPoolExecutor(num_executor) as t:
while True:
if q.empty():
break
data = q.get()
t.submit(insert_db_data, data)
## main函数
def spider():
get_url(q, end_time)
get_url_info(q)
return db_insert_data
## 全局函数
q = Queue()
begin_time = datetime.now()
end_time = datetime(2023, 10, 1)
db_insert_data = []
num_executor = 5
spider()