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的简单数据类型和变量
什么是数据类型? 程序的本质就是驱使计算机去处理各种状态的变化,这些状态分为很多种. 例如英雄联盟游戏,一个人物角色有名字,钱,等级,装备等特性,大家第一时间会想到这么表示 名字:德玛西亚------ ...
- C#文件处理
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- ToDictionary用法
ToDictionary其实可以简单化,可以传两个lambada表达式,第一个是Key,第二个就是Value. ToDictionary( key => key.Attribute(" ...
- 希腊字母、拉丁字母、Markdown、拼写与读音中英对照表
大写 小写 中文名 英文 大写Markdown 小写Markdown 意义 阿尔法 Alpha A \alpha 角度.系数.角加速度.第一个.电离度.转化率 贝塔/毕塔 Beta B \beta 磁 ...
- 分享基于.NET MVC+EF CodeFirst+IOC+EasyUI的框架设计
**注:要做工,没什么时间,等有空时会上传到GIT,项目结构如上,简单的说一下: **支持IOC及多数据库等,各项目由MVC区域隔离: 主要使用基于接口与抽象类进行高度的抽象与接口隔离,与其它框架比较 ...
- ngDialog 设置其宽度大小
[ngdialog弹窗大小设置(angularjs)] 方法一:添加css样式属性 css: .ngdialog.ngdialog-theme-plain.custom-width-70 .ngdia ...
- [6278009]使用Visual Stuido Code 编写Markdown
使用Visual Stuido Code 编写Markdown void main() { printf("Hello world!"); } void main() { Cons ...
- 总结:liunx常见命令集合
没有系统学习过liunx,把工作中遇到的liunx命令集合信息如下: 1.nc传送文件 之前总是用rsync, 今天遇到了一个从阿里云服务器传送文件到我们公司的内网服务器,这就不能传了,又想用一致的文 ...
- 创建 userSettings/Microsoft.SqlServer.Configuration.LandingPage.Properties.Settings 的配置节处理程序时出错: 未能加载文件或程序集“System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089”或它的某一个依赖项。系统没找到指定的文件
创建 userSettings/Microsoft.SqlServer.Configuration.LandingPage.Properties.Settings 的配置节处理程序时出错: 未能加载文 ...
- JQuery-常用小组件
常用的小组件记录 1. 单选框.复选框重置样式效果 参考: http://www.cnblogs.com/sanshi/p/4369375.html 三生石上 参考: http://www.jq22. ...