吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2495|回复: 17
收起左侧

[Python 转载] python 多线程/多进程 爬取关联网页信息

  [复制链接]
D.A. 发表于 2020-9-1 19:57
本帖最后由 D.A. 于 2020-9-1 21:30 编辑

最近想实现通过公司网站爬取网页内置链接并汇总文字信息,折腾了一通本来可以实现了,但是要爬取对象多内置链接也多,速度太慢,遂学习了一下多进程在python爬取中的实现方式,和大家分享一下。
补充了多线程爬取效果对比,由于有网页响应时间影响,无法直接判断哪个方式更快,但整体而言两种方式速度都比普通模式快很多。
模式 普通模式多线程模式 多进程模式
时间 257.9s 200.2s 196.7s


爬取思路:
1、根据公司网站内容获取内置链接:
[Python] 纯文本查看 复制代码
#获取网页文本
def getpage(url):
    try:
        res = requests.get(url, headers, timeout = 30)
        res.encoding = res.apparent_encoding
        text = res.text
    except:
        text = ''
    return text
links = ['http://www.fourd.cn', 'http://www.tfsea.com.cn', 'http://www.csscwshi.com' ,'http://www.marina-zh.com/', 'http://www.gdmoko.cn']
for rawlink in links:
    rawtext = getpage(rawlink)  # 获取网页信息
    link_list = re.findall(r"(?<=href=\").+?(?=\")|(?<=href=\').+?(?=\')", rawtext)  # 获取网页内含链接
    link_list = list(set(link_list))  # 去除重复项


2、获取网页内可访问链接
[Python] 纯文本查看 复制代码
#获取网页内可访问链接
        csurls = []
        for link in link_list:
            if getcode(link) == 200:
                csurl = link
            elif getcode('http://' + link) == 200:
                csurl = 'http://' + link
            elif getcode('https://' + link) == 200:
                csurl = 'https://' + link
            elif getcode(rawlink + '//' + link) == 200:
                csurl = rawlink + link
            else:
                csurl =""
            csurls.append(csurl)
            csurls = [x for x in csurls if x != '']#删除列表空值


3、根据关联链接获取中文文本信息
[Python] 纯文本查看 复制代码
# 获取网页中文文本
def getchtext(url):
    text = getpage(url)
    chinese_pattern = '[\u4e00-\u9fa5]+'
    chtexts = re.findall(chinese_pattern, text)
    chtexts = list(set(chtexts)) #去重
    chtexts = " ".join(chtexts)
    return chtexts
res = []
for csurl in csurls:
    res.append(getchtext(csurl))


4、设置进程池实现多进程爬取
以下内容替代第三步中的最后三行
[Python] 纯文本查看 复制代码
        #设置多核进程池
pool = mp.Pool(processes=2) #设置多进程数量,可不设置
es = pool.map(getchtext, csurls)#多进程获取网页内置链接中文信息
pool.close()
pool.join()



5、设置多线程爬取
getchtext函数需同步修改,因多线程无法直接return,需引入queen取数。后半部分替换第三步中最后三行
[Python] 纯文本查看 复制代码
# 获取网页中文文本
def getchtext(url,q):
    text = getpage(url)
    chinese_pattern = '[\u4e00-\u9fa5]+'
    chtexts = re.findall(chinese_pattern, text)
    chtexts = list(set(chtexts)) #去重
    chtexts = " ".join(chtexts)
    q.put(chtexts)

# 多线程模式运行
q = Queue()
threads = []
for i in range(len(csurls)):
    t = threading.Thread(target= getchtext, args=(csurls[i], q))
    t.start()
    threads.append(t)
for thread in threads:
    thread.join()
    res =[]
for _ in range(len(csurls)):
    res.append(q.get())


多进程完整代码如下:
[Python] 纯文本查看 复制代码
import requests
import time
import re
from fake_useragent import UserAgent
import multiprocessing as mp

#设置headers
ua = UserAgent(verify_ssl=False)
headers = {
    "User-Agent": ua.random,
    }

#获取网页文本
def getpage(url):
    try:
        res = requests.get(url, headers, timeout = 30)
        res.encoding = res.apparent_encoding
        text = res.text
    except:
        text = ''
    return text

#获取网页状态码
def getcode(url):
    try:
        res = requests.get(url, headers, timeout = 30)
        code = res.status_code
    except:
        code = 0
    return code

# 获取网页中文文本
def getchtext(url):
    text = getpage(url)
    chinese_pattern = '[\u4e00-\u9fa5]+'
    chtexts = re.findall(chinese_pattern, text)
    chtexts = list(set(chtexts)) #去重
    chtexts = " ".join(chtexts)
    return chtexts

#获取网页及关联网页信息
if __name__ == '__main__':
    start = time.time()
    links = ['http://www.fourd.cn', 'http://www.tfsea.com.cn', 'http://www.csscwshi.com' ,'http://www.marina-zh.com/', 'http://www.gdmoko.cn']
    for rawlink in links:
        rawtext = getpage(rawlink)  # 获取网页信息
        corpchtext = getchtext(rawlink)  # 获取网页中文文本信息
        link_list = re.findall(r"(?<=href=\").+?(?=\")|(?<=href=\').+?(?=\')", rawtext)  # 获取网页内含链接
        link_list = list(set(link_list))  # 去除重复项
        #获取网页内可访问链接
        csurls = []
        for link in link_list:
            if getcode(link) == 200:
                csurl = link
            elif getcode('http://' + link) == 200:
                csurl = 'http://' + link
            elif getcode('https://' + link) == 200:
                csurl = 'https://' + link
            elif getcode(rawlink + '//' + link) == 200:
                csurl = rawlink + link
            else:
                csurl =""
            csurls.append(csurl)
            csurls = [x for x in csurls if x != '']
        print('关联网址为:\n',csurls)
        #设置多核进程池
        pool = mp.Pool(processes=2) #设置多进程数量
        res = pool.map(getchtext, csurls)#多进程获取网页内置链接中文信息
        pool.close()
        pool.join()
        #汇总所有信息
        corptext = " ".join(res) + corpchtext
        print('公司网页信息汇总:\n',corptext)
    end = time.time()
    cost = end - start
    print('共花费{}s'.format(cost))


    #弹窗提醒
    from tkinter import messagebox
    messagebox.showinfo("提示","信息采集完成!")





多线程完整代码如下:
[Python] 纯文本查看 复制代码
import requests
import time
import re
from fake_useragent import UserAgent
import multiprocessing as mp
import threading
from queue import Queue

#设置headers
ua = UserAgent(verify_ssl=False)
headers = {
    "User-Agent": ua.random,
    }

#获取网页文本
def getpage(url):
    try:
        res = requests.get(url, headers, timeout = 30)
        res.encoding = res.apparent_encoding
        text = res.text
    except:
        text = ''
    return text

#获取网页状态码
def getcode(url):
    try:
        res = requests.get(url, headers, timeout = 30)
        code = res.status_code
    except:
        code = 0
    return code

# 获取网页中文文本
def getchtext(url,q):
    text = getpage(url)
    chinese_pattern = '[\u4e00-\u9fa5]+'
    chtexts = re.findall(chinese_pattern, text)
    chtexts = list(set(chtexts)) #去重
    chtexts = " ".join(chtexts)
    q.put(chtexts)

#获取网页及关联网页信息
if __name__ == '__main__':
    start = time.time()
    links = ['http://www.fourd.cn', 'http://www.tfsea.com.cn', 'http://www.csscwshi.com' ,'http://www.marina-zh.com/', 'http://www.gdmoko.cn']
    for rawlink in links:
        rawtext = getpage(rawlink)  # 获取网页信息
        #corpchtext = getchtext(rawlink)  # 获取网页中文文本信息
        link_list = re.findall(r"(?<=href=\").+?(?=\")|(?<=href=\').+?(?=\')", rawtext)  # 获取网页内含链接
        link_list = list(set(link_list))  # 去除重复项
        #获取网页内可访问链接
        csurls = []
        for link in link_list:
            if getcode(link) == 200:
                csurl = link
            elif getcode('http://' + link) == 200:
                csurl = 'http://' + link
            elif getcode('https://' + link) == 200:
                csurl = 'https://' + link
            elif getcode(rawlink + '//' + link) == 200:
                csurl = rawlink + link
            else:
                csurl =""
            csurls.append(csurl)
            csurls = [x for x in csurls if x != '']
        print('关联网址为:\n',csurls)


        #多线程模式运行
        q = Queue()
        threads = []
        for i in range(len(csurls)):
            t = threading.Thread(target= getchtext, args=(csurls[i], q))
            t.start()
            threads.append(t)
        for thread in threads:
            thread.join()
        res =[]
        for _ in range(len(csurls)):
            res.append(q.get())


        #汇总所有信息
        corptext = " ".join(res) #+ corpchtext
        print('公司网页信息汇总:\n',corptext)
    end = time.time()
    cost = end - start
    print('共花费{}s'.format(cost))


    #弹窗提醒
    from tkinter import messagebox
    messagebox.showinfo("提示","信息采集完成!")

免费评分

参与人数 4吾爱币 +4 热心值 +4 收起 理由
shlboliqiao + 1 + 1 我很赞同!
JavaSB + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
BLACKSUZAKU + 1 + 1 666
Zeaf + 1 + 1 我很赞同!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

thepoy 发表于 2020-9-1 21:30
本帖最后由 thepoy 于 2020-9-1 21:31 编辑
darling.青年 发表于 2020-9-1 20:26
不是说python的多线程是假的吗?全局解释器锁

是假的,但当一个线程遇到I/O任务时,会释放GIL,所以在爬虫这种I/O密集型操作上,python的多线程还是有明显的效率提升的。可以理解为,当一个线程在网络I/O时会切换到下一个线程,这样会节省很多网络响应的等待时间,也就会变快了。
阳光肥肥 发表于 2020-9-1 21:06
darling.青年 发表于 2020-9-1 20:26
不是说python的多线程是假的吗?全局解释器锁

在等待网络IO的时候 GIL会被释放
所以IO密集型的时候 多线程还是优于多进程
Zeaf 发表于 2020-9-1 20:01
不知道为什么,我感觉多线程比多进程快得多?
头像被屏蔽
算法分析 发表于 2020-9-1 20:15
提示: 作者被禁止或删除 内容自动屏蔽
ghoob321 发表于 2020-9-1 20:16
多线程比多进程快
leo580 发表于 2020-9-1 20:22
Zeaf 发表于 2020-9-1 20:01
不知道为什么,我感觉多线程比多进程快得多?

能分享下,多线程的源码,学习下。谢谢。
darling.青年 发表于 2020-9-1 20:26
不是说python的多线程是假的吗?全局解释器锁
smile_good123 发表于 2020-9-1 20:35
简单明了,谢谢分享!
fanvalen 发表于 2020-9-1 20:37
ghoob321 发表于 2020-9-1 20:16
多线程比多进程快

多进程受限制于CPU核心数量
 楼主| D.A. 发表于 2020-9-1 20:42
ghoob321 发表于 2020-9-1 20:16
多线程比多进程快

是吗?我学的时候都说多进程快
Zeaf 发表于 2020-9-1 21:05
leo580 发表于 2020-9-1 20:22
能分享下,多线程的源码,学习下。谢谢。

你就是查论坛或者CSDN都有很多啊~比如本论坛最新的https://www.52pojie.cn/thread-1258440-1-1.html
多线程理论上就是传递不同参数给不同线程就可以了
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-22 06:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表