day10、抓取m.sohu.com的所有页面,并且存入redis

太复杂。本人不会

import requests
from lxml import etree
from urllib.parse import urlparse
from time import sleep

from threading import Thread
from queue import Queue
import sys
from redis import Redis
# 用IDLE来记录线程的空闲
IDLE = 0
# 用WORKING来记录线程的工作状态
WORKING = 1

rds  = Redis("127.0.0.1",6379,db=10)

# 定义一个装饰器对象
class retry(object):
    def __init__(self,max_tries=3,wait=3,exceptions=(Exception,)):
        self.max_tries = max_tries
        self.wait = wait
        self.exceptions = exceptions

    def __call__(self, f):
        def wrapper(*args,**kwargs):
            for i in range(self.max_tries+1):
                try:
                    result = f(*args,**kwargs)
                except self.exceptions as e:
                    print("waitting",e)
                    sleep(self.wait) # 如果有异常休眠一会再请求
                    print("retry %s "%(i+1))
                    continue
                else:
                    return result
        return wrapper


# 定义一个集合,用于存放访问过的网址
REQUESTED_URL = set()
# 下载页面
@retry(3,3)
def fetch(url):
    print(f'Fetching: {url}')
    res = requests.get(url)
    # 请求过以后,把网址添加到集合中
    REQUESTED_URL.add(url)
    # 请求成功,把页面内容返回出去
    if res.status_code == 200:
        return res.text
    return None

# 解析数据
def paese(html):
    # 剔除一些无效的url对应的页面
    if html in [None,'',b'']:
        return []
    # 通过xpath语法寻找a标签
    doc = etree.HTML(html)
    if doc is None:
        return []

    # 取当前页面中url
    urls = doc.xpath("//a/@href")

    # print(urls)
    # 对页面上获取到的链接进行清洗
    # 定义一个列表,用于存放清洗完成url
    url_list = []
    for ori_url in urls:
        parse_url = urlparse(ori_url) # ParseResult(scheme='', netloc='', path='/a/249902322_102150', params='', query='_f=m-index_business_news_9', fragment='')
        # print(parse_url)
        # 过滤域名
        domain = parse_url.netloc.strip() or "m.sohu.com"
        if domain == "m.sohu.com":
            # 过滤协议
            scheme = parse_url.scheme.strip() or "http"
            path = parse_url.path.strip()
            query = f'?{parse_url.query}'.strip() if parse_url.query else ''
            # 拼接url
            url = f'{scheme}://{domain}{path}{query}'
            # 把拼接好的url存储
            url_list.append(url)
    return url_list


# 定义一个函数调用下载与解析
def get_and_parse(url,url_queue):
    html = fetch(url)
    # paese(html)
    # print(html)
    for url in paese(html):
        url_queue.put(url)

# #定义一个函数,用于处理线程
# def process(url_list):
#     queue = Queue()
#     workers = []
#     for url in url_list:
#         t = Thread(target=get_and_parse,args=(url,queue))
#         t.setDaemon(True)
#         workers.append(t)
#         t.start()
#     for t in workers:
#         t.join()
#     return list(queue.queue)

# 创建一个多线程爬虫类
class Spider(Thread):
    # def __init__(self,todo_list):
    def __init__(self):
        super().__init__()
        # self.todo_list = todo_list
        self.stat = IDLE

    def is_idle(self):
        return self.stat == IDLE

    def run(self):
        while True:
            url = rds.blpop("TODO_LIST")[1]
            # url = self.todo_list.get()
            # 开始抓取
            self.stat = WORKING
            html = fetch(url)

            # url_list = set(paese(html))
            # url_list -= REQUESTED_URL
            url_list = set([url.encode('utf-8') for url in paese(html)])
            url_list -= rds.smembers("REQUEST_URL") # 去重

            # # 将新得到的url添加到循环里面
            # for url in url_list:
            #     self.todo_list.put(url)
            if url_list:
                rds.lpush("TODO_LIST",*url_list)

            # 把工作状态设置为空闲
            self.stat = IDLE


def main(max_threads):
    # 添加任务
    print("Start")
    # todo_list = Queue() # 待抓取的url
    # todo_list.put("http://m.sohu.com")
    print(rds.lpush("TODO_LIST","http://m.sohu.com/"))
    # 创建n个线程,并启动
    # spiders = [Spider(todo_list) for i in range(max_threads)]
    spiders = [Spider() for i in range(max_threads)]
    for spd in spiders:
        spd.start()

    # 检测所有的线程是否全部完成工作
    while True:
        # 改成redis键的判断
        # if todo_list.empty() and  [spd.is_idle() for spd in spiders]:
        if rds.llen("TODO_LIST")==0 and [spd.is_idle() for spd in spiders]:
            # 当前待抓取的列表为空,所有的线程也全部为空闲,退出程序
            print("所有的工作都完成了")
            sys.exit(0)
        else:
            print("REQUESRED %d" % rds.scard("REQUEST_URL"))
            sleep(1)

if __name__ == '__main__':
    if len(sys.argv) >= 2:
        max_threads = int(sys.argv[1])
        main(max_threads)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,133评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,682评论 3 390
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,784评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,508评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,603评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,607评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,604评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,359评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,805评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,121评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,280评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,959评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,588评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,206评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,442评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,193评论 2 367
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,144评论 2 352

推荐阅读更多精彩内容

  • 众所周知,微波炉现在可以说是遍地都有,但是什么容器能去加热呢?这可就需要我们好好看看了! 对于可以在微波炉里使用的...
    wj557321阅读 366评论 0 0
  • 十一年前,梁智与亡妻的女儿灵灵失踪。 据邻居说,最后看见是灵灵被常跟她一起玩耍的邻居哥哥小杰牵着手离开小区的。两个...
    回聲echo阅读 225评论 0 0
  • 注目她 当茂密的长发一根根飘落 拥抱她 当大地的体温一天天冷却 派对快结束了 惟有金色的叶子 无比辉煌
    蓝柿阅读 185评论 3 2
  • 越长大越会知道:当你累了,会有很多人对你说,累就别干了,可没人愿意给你钱花;当你生病了,会有很多人对你说,吃点药吧...
    罗掌柜real阅读 136评论 0 0