python网络爬虫之使用scrapy自动登录网站:https://www.cnblogs.com/zhanghongfeng/p/7684415.html
Scrapy笔记(11)- 模拟登录:https://blog.csdn.net/sdulsj/article/details/52984874
python爬虫之scrapy模拟登录:https://www.cnblogs.com/lei0213/p/8203521.html
Requests and Responses 官方参考文档:https://doc.scrapy.org/en/1.3/topics/request-response.html
一帧网不登录的时候,“排行榜单”可以查看 30条数据,登录之后可以查看 100条数据。
首先打开 fiddler(fiddler介绍及使用教程:https://blog.csdn.net/freeking101/article/category/6531758),如图:
然后打开一帧的登录页面,输入账号、密码,点击创作者登录,如图:
登录之后在打开 fiddler ,发现 fiddler 已经抓取了从登录到登录成功后的所有http 包,如图:
登录的 URL 找到了,还有发送的 post 数据找到了,下面就是写代码模拟 post 请求登录了。
只要登录后,就可以访问登录后任意一个页面。
现在我需要的数据是“热度榜单”,通过fiddle 抓包 和对比 网页上显示数据,需要的数据如图所示:
把 fiddle 抓取到的 json 数据复制下来,然后随便找一个 “json 在线解析工具”粘贴上去,就可以看到结果。
展开上面的 list 节点,可以看到 有 100条数据,因展开太长,截图没有展开。
模拟登陆 一帧网 示例代码:
#!/usr/bin/python3 # -*- coding: utf-8 -*- import scrapy import time import json class SlaveSpider(scrapy.Spider): name = "master_yizhen" start_urls = ['http://www.1zhen.com/api/user/login'] main_url = 'http://www.1zhen.com/account' login_url = start_urls[0] login_headers = { 'Host': 'www.1zhen.com', "Connection": "keep-alive", 'Accept': 'application/json, text/plain, */*', 'X-Requested-With': 'XMLHttpRequest', 'Origin': 'http://www.1zhen.com', 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) ' 'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.79 Safari/537.36', 'Content-Type': 'application/json;charset=UTF-8', 'Referer': 'http://www.1zhen.com/account', 'Accept-Encoding': 'gzip, deflate', 'Accept-Language': 'zh-CN,zh;q=0.9' } form_data = { "mobile": "12345678901", # 抓取 的 登陆的账号(手机号) "password": "加密密码", # 抓取 的 加密的密码 "role": "author" } def __init__(self): super(SlaveSpider, self).__init__() self.__base_url = 'http://www.1zhen.com' def start_requests(self): ''' # 如果登录 url 在浏览器中能打开,也可以使用这个方法进行登录 yield scrapy.Request( url=self.login_url, headers=self.login_headers, meta={'cookiejar': 1}, callback=self.login, # 登录函数 ) ''' # 如果登录 url 在浏览器中打开返回 404 ,则只有使用下面。 # 一帧网(http://www.1zhen.com/)登录页面(http://www.1zhen.com/api/user/login)就属于返回 404这种类型 yield scrapy.Request( url=self.login_url, headers=self.login_headers, meta={'cookiejar': 1}, callback=self.after_login, method='post', # 设置请求方法为 post 请求 body=json.dumps(self.form_data) # 设置请求体,即请求参数 ) # 通过上面 fiddle 抓取的 请求登录 的 URL ,可以看到 请求登录的URL使用的是 post 方法 def login(self, response): # 这个函数使用与 当 登录页面可以访问时的情况 print(response.url) print(response.text) form_data = { "mobile": "12345678901", # 抓取 的 登录账号 "password": "加密的密码", # 抓取 的 加密密码 "role": "author" } yield scrapy.FormRequest.from_response( response, formdata=form_data, headers=self.login_headers, meta={'cookiejar': response.meta['cookiejar']}, callback=self.after_login, ) def after_login(self, response): print(response.url) t = time.localtime(time.time()) week_time = '{0}-{1}-{2}'.format(t.tm_year, t.tm_mon, t.tm_mday) page_url = '{0}/api/rank/author?during=week&pt_week={1}&platform=all&category=1'.format( self.__base_url, week_time ) # 构造请求的 URL yield scrapy.Request( url=page_url, headers=self.login_headers, meta={'cookiejar': response.meta['cookiejar']}, callback=self.parse_data ) # 通过上面 fiddle 抓包,可以看到请求的 URL 使用的 get 方法 pass def parse_data(self, response): data = json.dumps(response.text, ensure_ascii=False, indent=4) print(data) pass
运行结果截图:
网上找的一个使用 scrapy 模拟登录的示例代码:
#!/usr/bin/python3 # -*- coding: utf-8 -*- import scrapy from scrapy import FormRequest, Request class ExampleLoginSpider(scrapy.Spider): name = "login_" allowed_domains = ["example.webscraping.com"] start_urls = ['http://example.webscraping.com/user/profile'] login_url = 'http://example.webscraping.com/places/default/user/login' def parse(self, response): print(response.text) def start_requests(self): yield scrapy.Request(self.login_url, callback=self.login) def login(self, response): form_data = { 'email': '[email protected]', 'password': '12345678' } yield FormRequest.from_response(response, formdata=form_data, callback=self.parse_login) def parse_login(self, response): # print('>>>>>>>>'+response.text) if 'Welcome Liu' in response.text: yield from super().start_requests()
上面是使用 scrapy 进行模拟登录
现在不使用scrapy 这个框架,使用 python 的 requests 这个牛逼的模块进行模拟登录,并把数据存到本地 redis 里面
代码如下:
#!/usr/bin/python3 # -*- coding: utf-8 -*- # @Author : # @File : general.py # @Software : PyCharm # @description : import requests import json import redis import hashlib import time class OneZhen(object): def __init__(self): self.__custom_headers = { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8", "Accept-Encoding": "gzip, deflate", "Accept-Language": "zh-CN,zh;q=0.8,en;q=0.6", "Cache-Control": "max-age=0", "Connection": "keep-alive", "Content-Type": "application/x-www-form-urlencoded", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36", "Referer": "http://www.1zhen.com/account", "Host": "www.1zhen.com", } self.__post_data = { "mobile": "12345678901", # 登录的账号 "password": "加密的密码", # 加密的密码 "role": "author", } self.__login_url = 'http://www.1zhen.com/api/user/login' self.__base_url = 'http://www.1zhen.com' self.data = None self.__session = requests.session() # 定义 session 会话(session可以自动管理cookies, scrapy貌似需要通过meta传递cookies) self.__session.headers = self.__custom_headers # 设置请求头 def login_onezhen(self, week_time): r = self.__session.post(self.__login_url, self.__post_data) if r.status_code == 200: # print(r.content) page_url = '{0}/api/rank/author?during=week&pt_week={1}&platform=all&category=1'.format(self.__base_url, week_time) page_content = self.__session.get(url=page_url) json_data = page_content.content.decode('utf-8') self.data = json.loads(json_data) else: print('login fail and status_code is {0}'.format(r.status_code)) return self.data def get_data(self, week_time): return self.login_onezhen(week_time) redis_host = '127.0.0.1' redis_port = 6379 r_db = redis.Redis(host=redis_host, port=redis_port, db=0) def write_redis(key, data_dict): r_db.hmset(key, data_dict) pass def main(): # current_time = '2018-06-19' t = time.localtime(time.time()) current_time = '{0}-{1}-{2}'.format(t.tm_year, t.tm_mon, t.tm_mday) onezhen = OneZhen() data = onezhen.get_data(current_time) print('from yizhen get data success and write redis...') for d in data['data']['list']: # key = md5(d['author']['name']) user_name = d['author']['name'] user_info = dict( name=user_name, head_img_url_yizhen=d['author']['avatar'], category=d['author']['category'] ) write_redis(d['author']['name'], user_info) print('write redis success and exit') def md5(src): m = hashlib.md5() m.update(src.encode('UTF-8')) return m.hexdigest() if __name__ == "__main__": main() pass
通过 Redis Desktop Manager 连接到本地 Redis ,可以看到本地 Redis 里面的数据。