python基础23(2025.6.29)分布式爬虫(增量式爬虫去重)&redis应用_(未完成!)

发布于:2025-06-30 ⋅ 阅读:(16) ⋅ 点赞:(0)

本次写一个爬取网易新闻的案例。因为redis能处理高并发,存储数据也可以,故不用mysql。而且新闻网站容易更新很多,而mysql只能持久化存储。

import scrapy
import re
import json
import redis  # 用它来去除重复, 记录访问过的url


class WangyiSpider(scrapy.Spider):
    name = "wangyi"
    allowed_domains = ["163.com"]
    start_urls = ["https://news.163.com/special/cm_guoji/?callback=data_callback"]

    code_re_obj = re.compile(r"data_callback\((?P<code>.*)\)", re.S) # 1

    conn = redis.Redis(host="127.0.0.1", port=6379, password="123456", db=4, decode_responses=True)

    def parse(self, resp, **kwargs):
        # 执行后续操作之前. 一定要先确认好. 你收到的东西对不对.
        # print(resp.text)
        # scrapy获取json格式的数据. 可以直接resp.json(), 直接拿到字典
        # json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
        # 典型的. 你拿到的数据不是json
        # print(resp.json())

        code = WangyiSpider.code_re_obj.search(resp.text).group("code")
        news = json.loads(code)
        for new in news:
            # print(new.get("tlink"))
            # print(new['tlink'])
            # print(new['title'])
            # 我要采集新闻的内容
            # 发请求. 获取到详情页中的内容

            # 需要判断该url是否已经被访问过了.
            # 必须得知道我访问过什么 需要把已经访问过的东西记录下来.
            tlink = new['tlink']
            if self.conn.sismember("news:wangyi", tlink):
                print("已经访问过了. ")
            else:
                yield scrapy.Request(url=new['tlink'], callback=self.parse_detail)

            # 用url进行控制是否访问过了   # 77777 9999
            # 如果是post请求呢?
            # http://www.baidu.com/a/b  formdata: id=10086  => 樵夫11爱你
            # http://www.baidu.com/a/b  formdata: id=10087  => 樵夫12爱你
            # http://www.baidu.com/a/b  formdata: id=10088  => 樵夫2123爱你
            # http://www.baidu.com/a/b  formdata: id=10089  => 樵夫12321爱你

            # 增量爬虫. 但是这个增量爬虫和樵夫讲的不一样了. 樵夫去重复用的是url. 每个详情页的url都是不一样的
            # 增量爬虫的核心逻辑是  去除重复.

        # data_callback([{title: "韩男子性侵)", ....}])
        # 这是典型的jsonp的逻辑
        #  xxxxxx(数据)
        # 可以用正则表达式来完成数据的提取

    def parse_detail(self, resp):
        print(resp.url)
        post_body = resp.xpath("//div[@class='post_body']/p/text()").extract()
        post_title = resp.xpath("//h1[@class='post_title']/text()").extract_first()
        post_body = "".join(post_body).strip()
        print(post_title, post_body)
        # 16个库.
        # news:
        #   wangyi
        #   tengxun
        #   xxxx
        self.conn.sadd("news:wangyi", resp.url) #2

运行的讲解一:开启redis
在这里插入图片描述

在这里插入图片描述
这里的意思是,我们为了“验证访问的url”每次访问都是不一样的,如果访问了,我们就不再访问

但是如果是post请求,我们就可以如上图那样记录“不一样的参数”

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到