本次写一个爬取网易新闻的案例。因为redis能处理高并发,存储数据也可以,故不用mysql。而且新闻网站容易更新很多,而mysql只能持久化存储。
import scrapy
import re
import json
import redis # 用它来去除重复, 记录访问过的urlclass 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) # 1conn = 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# xxxxself.conn.sadd("news:wangyi", resp.url) #2
运行的讲解一:开启redis
这里的意思是,我们为了“验证访问的url”每次访问都是不一样的,如果访问了,我们就不再访问
但是如果是post请求,我们就可以如上图那样记录“不一样的参数”