scrapy 知乎的模拟登陆及抓取用户数据
最近看了python的scrapy 框架并用其抓取了部分知乎用户数据,代码主要是集中在知乎登陆和抓取时候的逻辑处理上。
1、 首先进入知乎登陆页面zhihu.com/#sigin上, 用xpath提取_xsrf参数, 获取验证码的部分url,完整的url是由当前的时间戳和type参数构成,利用得到的url形成response, 在函数handle_captcha对验证码提取并提示在终端输入验证码,最后再将登陆的url、cookie、用户账号、密码什么的from进去就可以登陆成功了。下面是代码:
# _*_coding:utf-8_*_ from scrapy.spider import CrawlSpider
from scrapy.http import Request, FormRequest
from scrapy.selector import Selector
from zhihu2 import config
from PIL import Image
import time
import json
import re
from zhihu2 import items class ZhiHu_spider(CrawlSpider):
name = 'zhihu2'
allowed_domain = ['https://www.zhihu.com'] def __init__(self, *args, **kwargs):
super(ZhiHu_spider, self).__init__(*args, **kwargs)
self.xsrf = ''
self.headers = config.headers def start_requests(self):
yield Request(
'http://www.zhihu.com/#signin',
meta={
'cookiejar': 1
},
callback=self.post_login
) def post_login(self, response):
print 'parper login in '
sel = Selector(response)
self.xsrf = sel.xpath('//input[@name="_xsrf"]/@value').extract()[0] #验证码的获取 没有自动识别 识别率太低 所以手打
str_time = str(time.time() * 1000)
cap_url = 'https://www.zhihu.com/captcha.gif?r=' + str_time + '&type=login'
print cap_url
yield Request(
cap_url,
meta={'cookiejar': response.meta['cookiejar'],
'_xsrf': self.xsrf,
}, headers=self.headers,
callback=self.handle_captcha ) def handle_captcha(self, response):
with open('E:\\myscrapy\\captcha.gif', 'wb') as gif:
gif.write(response.body)
gif.close()
Im = Image.open('E:\\myscrapy\\captcha.gif')
Im.show()
captcha = raw_input('enter your captcha:') yield FormRequest(
'http://www.zhihu.com/login/phone_num', #s手机号登陆, 对应的可以换成邮箱
method='POST',
meta={'cookiejar': response.meta['cookiejar']},
headers=self.headers,
formdata={
'_xsrf': self.xsrf,
'password': '密码',
'remember_me': 'true',
'phone_num': '账号',
'captcha': captcha
},
callback=self.after_login, )
2、下面是登陆之后获取关注人的信息,由于知乎第一次只会显示20个关注人,剩下的要post数据到www.zhihu.com/node/ProfileFolloweesList2
才能又获取20个,所以在这要获取每个人的关注人数并与20做对比。
# 获取个人主页
def after_login(self, response):
print response.body
print 'login success'
yield Request(
'https://www.zhihu.com/people/你的id需要填写, #自己主页的网址 因为我没获取id 所以要输入自己主页的网址
meta={'cookiejar': response.meta['cookiejar']},
headers=self.headers,
callback=self.parse_people,
)
#获取关注人url
def parse_people(self, response):
# print 'ready'
sel = Selector(response)
follow_url = sel.xpath('//a[@class="item"]/@href').extract_first()
if follow_url:
compete_url = 'https://www.zhihu.com' + follow_url yield Request(
compete_url,
meta={
'cookiejar': response.meta['cookiejar'],
},
headers=self.headers,
callback=self.person_info,
) #处理关注人的url 并获取信息
def person_info(self, response):
item = items.Zhihu2Item()
count = 20
sel = Selector(response) nikname = sel.xpath('//div[@class="title-section"]/a[@class="name"]/text()').extract_first()
location = sel.xpath('//span[@class="location item"]/@title').extract_first()
business = sel.xpath('//span[@class="business item"]/@title').extract_first()
education = sel.xpath('//span[@class="education item"]/@title').extract_first()
education_extra = sel.xpath('//span[@class="education-extra item"]/@title').extract_first()
sex = sel.xpath('//span[@class="item gender"]/i/@class').extract_first().split('-')[-1]
agree = sel.xpath('//span[@class="zm-profile-header-user-agree"]/strong/text()').extract_first()
thanks = sel.xpath('//span[@class="zm-profile-header-user-thanks"]/strong/text()').extract_first() config.try_none(nikname)
config.try_none(location)
config.try_none(business)
config.try_none(education)
config.try_none(education_extra)
config.try_none(sex)
config.try_none(agree)
config.try_none(thanks) peo_num = sel.xpath('/html/body/div[3]/div[2]/div[1]/a[1]/strong/text()').extract_first()
item['nikname'] = nikname
item['business'] = business
item['education_extra'] = education_extra
item['location'] = location
item['education'] =education
item['sex'] = sex
item['agree'] = agree
item['thanks'] = thanks if peo_num: people_urls = sel.xpath('//a[@class="zg-link author-link"]/@href').extract()
for people_url in people_urls:
yield Request(
people_url,
meta={'cookiejar': response.meta['cookiejar']},
headers=self.headers,
callback=self.person_info
) peo_params = sel.xpath('//div[@class="zh-general-list clearfix"]/@data-init').extract_first()
if peo_params:
try:
values = json.loads(str(peo_params))
except ValueError, e:
print e.message
params = {}
params['offset'] = 20
params['order_by'] = 'created'
params['hash_id'] = values['params']['hash_id'] if count < peo_num:
params['offset'] = count
yield FormRequest(
'https://www.zhihu.com/node/ProfileFolloweesListV2',
method='POST',
meta={'cookiejar': response.meta['cookiejar']},
headers=self.headers,
formdata={
'method': 'next',
'params': json.dumps(params),
'_xsrf': self.xsrf,
},
callback=self.foolows_V2
)
count += 20
else:
num = peo_num / 20
params['offset'] = num
yield FormRequest(
'https://www.zhihu.com/node/ProfileFolloweesListV2',
method='POST',
meta={'cookiejar': response.meta['cookiejar']},
headers=self.headers,
formdata={
'method': 'next',
'params': json.dumps(params),
'_xsrf': self.xsrf,
},
callback=self.foolows_V2
)
3、从上面url的response获取关注人的url,得到的url 交由parse_people函数处理,parse_people函数的response交由person_info函数处理,所以就形成了一个循环,不断的有url被提取,也不断的有数据被提取出来,下面是parse_people函数的代码:
def foolows_V2(self, response):
p = re.compile(r'href="https://www\.zhihu\.com/people/(.*?)"') aa = json.loads(response.body)['msg']
for item in aa:
peo = p.search(item).group(1)
followes_url = 'https://www.zhihu.com/people/' + str(peo)
yield Request(
followes_url,
meta={'cookiejar': response.meta['cookiejar']},
headers=self.headers,
callback=self.parse_people
)
下面是一些配置信息:
cofig.py
#_*_coding:utf-8_*_ from settings import USER_AGENT headers = { 'Host': 'www.zhihu.com',
'Connection': 'keep-alive',
'Pragma': 'no-cache',
'Cache-Control': 'no-cache',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Origin': 'https://www.zhihu.com',
'X-Requested-With': 'XMLHttpRequest',
'User-Agent': USER_AGENT,
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Referer': 'https://www.zhihu.com/',
'Accept-Encoding': 'gzip,deflate,sdch',
'Accept-Language': 'zh-CN,zh;q=0.8',
} def try_none(tag):
try:
tag
except:
tag = 'none'
return tag
items.py:
from scrapy import Item, Field class Zhihu2Item(Item):
nikname = Field()
location = Field()
business = Field()
education = Field()
education_extra = Field()
sex = Field()
thanks = Field()
agree = Field()
代码没有维护已爬取的url和带爬取的url的重复,可能会导致重复抓取,代码的优化也挺烂的。希望大神们多给点意见,如果代码有错误,希望提出,以免给别人误导。
scrapy 知乎的模拟登陆及抓取用户数据的更多相关文章
- 【转】详解抓取网站,模拟登陆,抓取动态网页的原理和实现(Python,C#等)
转自:http://www.crifan.com/files/doc/docbook/web_scrape_emulate_login/release/html/web_scrape_emulate_ ...
- Scrapy模拟登陆豆瓣抓取数据
scrapy startproject douban 其中douban是我们的项目名称 2创建爬虫文件 进入到douban 然后创建爬虫文件 scrapy genspider dou douban. ...
- 爬虫模拟登陆之formdata表单数据
首先HTTP协议是个无连接的协议,浏览器和服务器之间是以循环往复的请求回复来交互的,交互的形式是以文件形式来进行的.比如在chrome开发者工具network中看到了 每一行是一个文件,又文件大小啊, ...
- Android(Java) 模拟登录知乎并抓取用户信息
前不久.看到一篇文章我用爬虫一天时间"偷了"知乎一百万用户.仅仅为证明PHP是世界上最好的语言,该文章中使用的登录方式是直接复制cookie到代码中,这里呢,我不以爬信息为目的.仅 ...
- Java模拟登陆新浪微博抓取数据【转载】
package com.shiyimm.crawler.weibo; import java.io.FileNotFoundException; import java.io.FileReader; ...
- Scrapy 模拟登陆知乎--抓取热点话题
工具准备 在开始之前,请确保 scrpay 正确安装,手头有一款简洁而强大的浏览器, 若是你有使用 postman 那就更好了. Python 1 scrapy genspid ...
- Scrapy 中的模拟登陆
目前,大部分网站都具有用户登陆功能,其中某些网站只有在用户登陆后才能获得有价值的信息,在爬取这类网站时,Scrapy 爬虫程序先模拟登陆,再爬取内容 1.登陆实质 其核心是想服务器发送含有登陆表单数据 ...
- 【教程】手把手教你如何利用工具(IE9的F12)去分析模拟登陆网站(百度首页)的内部逻辑过程
[前提] 想要实现使用某种语言,比如Python,C#等,去实现模拟登陆网站的话,首先要做的事情就是使用某种工具,去分析本身使用浏览器去登陆网页的时候,其内部的执行过程,内部逻辑. 此登陆的逻辑过程, ...
- 使用C#的HttpWebRequest模拟登陆访问人人网
使用任何语言做模拟登陆或者抓取访问页面,无外乎以下思路: 第一 启用一个web访问会话方法或者实例化一个web访问类,如.net中的HttpWebRequest:第二 模拟POST或者GET方式提交的 ...
随机推荐
- Python高手之路【十】python基础之反射
反射说简单点 --> 就是利用字符串的形式去对象(模块)中操作(寻找/检查/删除/设置)成员. 需求:由用户输入一个模块名,用户输入什么模块名,文件中就导入什么模块: 1:文件都在同一目录下的导 ...
- Maven配置插件跳过测试代码的编译和运行
Maven配置插件跳过测试代码的编译和运行: <!-- 编译插件 --> <plugin> <groupId>org.apache.maven.plugins< ...
- Linux sendmail 详解
Internet上最基本的服务,现在应该大部分人都有自己的邮箱吧,用的人多,但理解的人估计没多少,我自己以前也是常常用,但对其原理并不操心.今天就来操心下,进行个小总结 一.邮件服务的基本流程 ...
- Redis配置成系统服务(CentOS7)
1. 进入到redis安装目录,具体位置看你安装时的路径了. cd /usr/local/redis/ 2. 编辑配置文件 sudo vim ./redis.conf 3. 将如下配置项注释掉 #bi ...
- 单机Hadoop搭建
通过一段时间的学习,我在我的centos上安装了单机hadoop,如果这对你有帮助,就进来探讨学习一下 Hadoop伪分布式配置 Hadoop 可以在单节点上以伪分布式的方式运行,Hadoop 进程以 ...
- 关于Mac中Clion使用OpenCV
关于Mac中Clion使用OpenCV 目标 Clion能够使用OpenCV 步骤 下载安装cmake,官网下载 下载OpenCV mac/linux版 使用cmake gui编译opencv安装包, ...
- 130道C#面试题
C#/.Net/数据库笔试资料C#资料(一)1.静态成员和非静态成员的区别?答:静态变量使用 static 修饰符进行声明,在类被实例化时创建,通过类进行访问不带有 static 修饰符声明的变量称做 ...
- StringMVC(拦截器)
单个拦截器 使用jar包 创建FirstController.java @Controller public class FirstController { @RequestMapping(" ...
- myeclipse里如何添加mysql数据库
首先声明,这只是我本人的一些经验,不代表任何集体和个人的利益,请勿没事就当喷子来喷我.我希望对一些对这方面学习的朋友有帮助,当然,我自己也是菜鸟级别啦!!!!!!!!!!!! 首先是电脑必要安装了my ...
- 【angular】angular如何让传递变量参数+ng-change的使用
HTML: <div class="form-group"> <label class="col-sm-2 control-label"> ...