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方式提交的 ...
随机推荐
- SQL Server存储过程同时返回分页结果集和总数
前言 好长时间没摸数据库了,周末在家写了个报表的存储过程,一时间对使用存储过程实现分页的同时并计算出记录总数不知道怎么更好的去实现.按照我们正常的业务逻辑,存储过程数据首先是分页,其次接受若干查询条件 ...
- HDU 4777 Rabbit Kingdom
素因子分解,树状数组.$ACM/ICPC$ $2013$杭州区域赛$H$题. 首先需要处理出数字$a[i]$左边最远到$L[i]$,右边最远到$R[i]$区间内所有数字都与$a[i]$互质. 那么对于 ...
- itoa()函数和atoi()函数
1.int/float to string/array: C语言提供了几个标准库函数,可以将任意类型(整型.长整型.浮点型等)的数字转换为字符串,下面列举了各函数的方法及其说明.● itoa():将 ...
- Spark编程模型及RDD操作
转载自:http://blog.csdn.net/liuwenbo0920/article/details/45243775 1. Spark中的基本概念 在Spark中,有下面的基本概念.Appli ...
- hibernate子查询
对于支持子查询的数据库,Hibernate支持在查询中使用子查询.一个子查询必须被圆括号包围起来(经常是SQL聚集函数的圆括号). 甚至相互关联的子查询(引用到外部查询中的别名的子查询)也是允许的. ...
- js生成缩略图后上传并利用canvas重绘
function drawCanvasImage(obj,width, callback){ var $canvas = $('<canvas></canvas>'), can ...
- 第一百二十五节,JavaScript,XML
JavaScript,XML 学习要点: 1.IE中的XML 2.DOM2中的XML 3.跨浏览器处理XML 随着互联网的发展,Web应用程序的丰富,开发人员越来越希望能够使用客户端来操作XML技术. ...
- asp.net mvc 上传下载文件的几种方式
view: <!DOCTYPE html> <html> <head> <meta name="viewport" content=&qu ...
- 移动app安全测试
安全方面逐渐转向app安全,服务端app安全测试基本上跟常规的web方面挖掘差不多,只是增加了一个反编译或抓包的过程. 参考文献: http://drops.wooyun.org/tips/749 h ...
- Error C1189: #error: Please use the /MD switch for _AFXDLL builds
在VS 2013中编译程序时出现错误: 错误提示1: error C1189: #error : Building MFC application with /MD[d] (CRT dll versi ...