分布式爬取知乎
一、环境
- window7
- scrapy
- pycharm
- redis
- other PC
- MySQL
二、简介
之所以选择爬取知乎,一是很多人都在爬,那么一定有它爬取价值的地方;二呢分析后才发现,知乎是一个模拟登录、信息解析清洗、反反爬等较为经典的练习素材;我们在这次爬取中将会涉及到IP代理、随机更换UserAgent、scrapy-redis分布式。
数据维度:
问题:问题ID、标签、链接、题目、内容、问题创建时间、问题更新时间,回答数、评论数、关注数、浏览数、爬取时间、爬取更新时间
回答:回答ID、链接、问题ID、作者ID、内容、点赞数、评论数、回答创建时间、回答更新时间、爬取时间、爬取更新时间
三、网页分析与编程实现
一开始是使用scrapy直接模拟登录知乎后进行爬取,但到应用上redis后,发现其实不用登录也能爬取到知乎问答数据;这里既然需要介绍redis分布式爬取,就重点介绍应用redis分布式不登陆知乎的爬取方法,简单介绍下模拟登录下非分布式爬取。
知乎的模拟登录验证码的破解还是有点难度的,有时是数字字母验证,有时却是倒立的文字验证,验证方法我试过使用OCR自动识别数字字母,但识别准确度不高,还有待钻研 ,所以这次采用了较为便捷的selenium+webdriver方案
def start_requests(self): #scrapy 运行的入口,之前一直无法请求成功的原因是此处写成了start_request(self)
from selenium import webdriver
import time
import pickle
# Mycrawl_xici_ip.get_ips() #获取并保存IP
#ip_list_https = self.get_ip_list('https')
# with open('proxy_ip.txt' , 'r') as rf:
# ips_str = rf.read()
# ips_list = ips_str.split('\n')
try:
#response = scrapy.Request("http://ip.filefab.com/index.php") #测试,查看IP
f = open('E:/例程总汇/Python/ArticleSpider/ArticleSpider/cookies/zhihu/cookies.zhihu', 'rb')
cookie_dict = pickle.load(f)
f.close()
yield scrapy.Request(self.start_urls[1].format(6) , dont_filter=True, cookies=cookie_dict,
headers=self.header,callback=self.parse_JsonResponse , encoding="utf8" )
except:
brower = webdriver.Chrome(executable_path="D:/chromedriver/chromedriver.exe")
brower.get("https://www.zhihu.com/signin") # 进入登录界面
brower.find_element_by_css_selector(
".SignFlow-accountInput.Input-wrapper input[name='username']").send_keys(
USER) # 自动填充账号
brower.find_element_by_css_selector(".SignFlow-password .Input-wrapper input[name='password']").send_keys(
PASSWARD) # 自动填充密码
brower.find_element_by_css_selector(".Button.SignFlow-submitButton").click()
time.sleep(10) # 登录成功后自动跳转到首页,可以获取浏览cookies,验证已登录
Cookies = brower.get_cookies() # 获取cookies
# print(Cookies)
cookie_dict = {}
for cookie in Cookies:
cookie_dict[cookie["name"]] = cookie["value"]
# 写入文件
f = open('E:/例程总汇/Python/ArticleSpider/ArticleSpider/cookies/zhihu/cookies.zhihu', 'wb')
pickle.dump(cookie_dict, f)
f.close()
brower.close() # 浏览器关闭
yield scrapy.Request(self.start_urls[1].format(6) , dont_filter=True, cookies=cookie_dict, headers
=self.header , encoding="UTF8" , callback= self.parse_JsonResponse)
登录成功后获取cookie值,保存到本地,下次再次启动时取出cookie值一起发送请求即可,但是每个cookie值都是有不同的生命周期的,所以需要不定期更新本地的cookie值。
模拟登录介绍完了,接下来的数据解析等跟分布式爬取下的差不多,就直接介绍分布式爬取方式。
注意此时已经不是同一个项目工程了,此次分布式爬取不采用登录知乎,而是分析出页面中加载更多问题的url,