Cool_Breeze 发表于 2021-1-11 12:58

Python3 爬取网站收藏数超过70的 < 情侣网名 >

本帖最后由 Cool_Breeze 于 2021-1-11 21:32 编辑


因为网站页面很简单!非常适合新手练习!
没有开启多线程爬取网站,只是开启了多线程处理数据,供大家学习参考!(这里只是给大家参考一下多线程!)

为什么没有开启多线程访问网页呢?
因为我有一次在某个论坛发布了一篇帖子,多线程爬取MP3。
当时是晚上12点发布的,结果第二天早上去该网站播放音乐,播放不了了!
不知道是我发布帖子的原因,还是对方服务器的问题(总感觉对不住人家!毕竟是小网站嘛!)
然后我就把帖子也删了!


# coding=utf-8
# python 3.7

import urllib.request,urllib.error
import re
import threading
import multiprocessing
from time import sleep


# 保存网页内容
def dataFilter():
    # 设置了全局参数(方便),最好还是传参数
    global htmlQueue # 任务队列
    global some      # log文件
    global lock      # 文件锁
   
    while True:
      html = htmlQueue.get() # 从任务队列中获取任务(数据)
      if html is None: exit(0) #退出线程
      
      # 正则表达式获取数据
      favorites = re.compile(r'title="收藏">(\d+)</a>').findall(html)
      centent = re.compile(r'id="txt-\d+-\d+">(.*?)</p>').findall(html)
      
      # 收藏值大于 70 的保存
      tmp = []
      lock.acquire() # 当文件没有其他线程写入时写入文件
      for n in range(len(favorites)):
            if int(favorites) > 70:
                tmp.append(favorites)
                index = n*2
                tmp.append(centent)
                tmp.append(centent)
                some.write(','.join(tmp) + '\n')
                some.flush()
                tmp.clear()
      lock.release() # 写入文件完成,报告(默认为 1 )
   

# 获取一页网页数据
def GetHtml(url):
    # 浏览器头部信息
    head = {
    'Accept-Language': 'zh-CN,zh;q=0.9',
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.30 Safari/537.36"
    }
   
    req = urllib.request.Request(url=url, headers=head)
    # 这里可以加入 try 代码,处理打开网页失败情况
    response = urllib.request.urlopen(req)
    return response.read().decode('utf-8')

   


# 爬取网站IP
url = 'https://www.woyaogexing.com/name/ql/'

# 第一页
print(f'正在爬取第一页 {url}')
parent = GetHtml(url)

# 获取当前页面包含的所有下一页的IP
page = re.compile(r'/name/ql/(index_\d+.html)').findall(parent)
page = set(page)    # 集合去重
page = list(page)   # 转换回列表
page.sort()         # 排序

# 第一页包含的所有页面IP
print(page)


# log保存文件
some = open('some.txt', 'w', encoding='utf-8')
some.write('收藏数, 签名1, 签名2\n')

# 写入文件锁,只能单个写入,避免数据混淆
# 默认值为 1 (单个线程写入文件)
lock = threading.Semaphore()

# 线程任务队列
htmlQueue = multiprocessing.Queue()

# 管理所有线程的容器
threadList = []

# 开启4个线程
# 设置为守护线程,主线程退出后结束所有子线程,避免线程悬挂
maxThreadN = 4
for n in range(maxThreadN):
    tmp = threading.Thread(target=dataFilter, daemon=True)
    threadList.append(tmp)
    tmp.start()

# 向线程任务队列提交任务
for n in page:
    print(f'正在爬取 {n}')
    sleep(2) # 加上等待时间2秒,我们要对网站温柔一些
    htmlQueue.put(GetHtml(url + n))

# 任务完成,提交数据 None 结束所有线程
for n in range(maxThreadN):
    htmlQueue.put(None)

# 等待所有线程结束
for th in threadList:
    th.join()

# 最后关闭 log 文件
some.close()
input('所有任务完成!')



运行画面:
正在爬取第一页 https://www.woyaogexing.com/name/ql/
['index_2.html', 'index_3.html', 'index_4.html', 'index_5.html', 'index_6.html']
正在爬取 index_2.html
正在爬取 index_3.html
正在爬取 index_4.html
正在爬取 index_5.html
正在爬取 index_6.html
所有任务完成!


日志文件内容:
收藏数, 签名1, 签名2
121,ʕ•̫͡•ʔ想揪吗,ʔ•̫͡•ʕ诶~ 就不让你揪
135,茶尾布朗熊.,短卷可妮兔.
80,仲夏蝉鸣.,悸动难平.
113,星洲泛泛.,桃花灼灼.
139,没人暖手手,那就揣兜兜

补一张流程图,方便理解

以上有什么不对之处,请大家指正!

Cool_Breeze 发表于 2021-1-11 14:57

本帖最后由 Cool_Breeze 于 2021-1-11 21:35 编辑

多线程开了,等于没有开,因为在处理数据之前被阻塞了,应该把网页数据筛选后放入StringIO里面,在写入文件时再阻塞线程,那样多线程才能提前处理好数据,然后等待数据写入文件!
大家参考一下就好了,也不想改了!:keai

liuxia 发表于 2021-1-11 13:04

这个有点意思 啊

五畿七道 发表于 2021-1-11 13:24

好活,支持

xuejiqiao 发表于 2021-1-11 14:35

写的好,支持。学习了

流浪星空 发表于 2021-1-11 15:02

支持一下!
页: [1]
查看完整版本: Python3 爬取网站收藏数超过70的 < 情侣网名 >