Scrapy练习爬知乎第一辑

模仿网上的Scrapy程序,自己写了个爬虫。虽然是模仿,但是呢,好多都是自己去实践错了对了,整天都在苦闷之中度过,没办法,我的IQ较低,总是要学很久才能懂。。。。。。。

ps:运行这个程序你要安装scrapy、Selector等等(好多好烦,若是出错了,找找版本原因,因为我上次在ubuntu上就是scrapy0.14的,运行错误。。)

首先爬知乎首页,你第一得做好登录(这个woc郁闷死了,官方文档看了很久没看到,后来看了某些博客,尼玛就在官方文档里啊 ,怪没用心去理解:))

直接上代码把,因为解释好多都在代码中。。。

zhihu/zhihu/spiders/zhihu_spider.py  :

<pre name="code" class="python">#!/usr/bin/env python
# -*- coding:utf-8 -*-
import bs4
from scrapy.selector import Selector
from scrapy.spider import Spider
from scrapy.item import Item,Field
from scrapy.http import Request,FormRequest
from zhihu.items import ZhihuItem
import urllib
import urllib2
import cookielib
import re
#from zhihu.items import ZhihuItem

class ZhihuSpider(Spider):
    """通过知乎首页先获取一个用户的信息"""
    name="zhihuspider"
    #allowed_domains=["zhihu.com"]
    #先前没加#时,用户的知乎网址被过滤掉了,后来查了下官方文档,Filtered offsite request to 'www.othersite.com':但是,http://www.zhihu.com/people/nihisic 是属于zhihu.com的啊 为什么还会被过滤掉?
    start_urls=["http://www.zhihu.com/",]
    """~~~~~~~~~~~~~~~~~~~~~~~"""
    headers = {
    "Accept": "*/*",
    "Accept-Encoding": "gzip,deflate",
    "Accept-Language": "en-US,en;q=0.8,zh-TW;q=0.6,zh;q=0.4",
    "Connection": "keep-alive",
    "Content-Type":" application/x-www-form-urlencoded; charset=UTF-8",
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36",
    "Referer": "http://www.zhihu.com/"
    }


    def start_requests(self):
        return [Request("https://www.zhihu.com/login", meta = {'cookiejar' : 1}, callback = self.post_login)]
    #当我们单个spider中每次只有一个request时候,因为默认是使用一个cookiejar来处理,
    # 所以我们在发出request的时候,不需要手动使用meta来给它布置cookiejar,
    # 但是当单个spider多个request的时候,因为返回的每个response要求下一个request带的cookie都不同,
    # 所以每一次都要手动给每个request添加cookiejar来记录

    def post_login(self, response):
        print 'Preparing login'
        #下面这句话用于抓取请求网页后返回网页中的_xsrf字段的文字, 用于成功提交表单
        xsrf = Selector(response).xpath('//input[@name="_xsrf"]/@value').extract()[0]
        print xsrf#这个是看了某个博客写的登录知乎的,我不知道提交的还有这个xsrf
        #FormRequeset.from_response是Scrapy提供的一个函数, 用于post表单
        #登陆成功后, 会调用after_login回调函数
        return [FormRequest.from_response(response,#模拟头部信息
                                          meta = {'cookiejar' : response.meta['cookiejar']},
                                          headers = self.headers,  #注意此处的headers
                                          formdata = {
                                              '_xsrf': xsrf,
                                              'email': 'xxxxxxxxxxxx',
                                              'password': 'xxxxxxx'
                                          },
                                          callback = self.parse_page,
                                          dont_filter = True
        )]#这个官方文档都有。。。。我只是没有好好的理解。。。。

    def after_login(self, response) :
        for url in self.start_urls :
            yield self.make_requests_from_url(url)
    """~~~~~~~~~~~~~~~~~~~~~~~"""
    def parse_page(self,response):
	title=[]
	link=[]
        sel=Selector(response)
        sites=sel.xpath('//div[@class="feed-main"]/div[@class="source"]')
        for site in sites:
            title=site.xpath('a/@title').extract()#因为知乎话题的话是没有title这个标签的,所以抓出来是空白,若是知乎用户的话就不是空白。
            link=site.xpath('a/@href').extract()
            #出现了Request url must be str or unicode这个错,后解决了
	    if title:#判定是否是用户,若不是用户,title为空
		yield Request(url=link[0],callback=self.parse2)#url变成了这样url=[u'http://...']
	    if not title:
		yield Request(url='http://www.zhihu.com'+link[0],callback=self.parse2)

    def parse2(self,response):
        """
        解析用户的详细信息页面,使用bs4
        """
        soup = bs4.BeautifulSoup(response.body,from_encoding="utf8")
        userInfo1 = soup.findAll('div', attrs={'class':'title-section ellipsis'})
	#这是个人知乎用户,因为class不同,所以与知乎话题userinfo2分开,下面筛的是知乎话题。
	userInfo2 = soup.findAll('div', attrs={'class':'zu-main-content'})
	if userInfo2:
	   # userInfo2 = userInfo2[0]
	   # item = ZhihuItem()
           # item['signature'] = "".join(userInfo2.findAll('div', attrs={'class':'zm-editable-content'})[0].strings)
           # item['yonghu'] = "".join(userInfo2.findAll('h1', attrs={'class':'zm-editable-content'})[0].strings)
	   pass#啊西吧   若是取消#,则会出现list out of range,又是这种错误,好烦。。。。直接pass
           # print item['signature']
           # print item['yonghu']
           # return item

        if userInfo1:
            userInfo1 = userInfo1[0]
            item = ZhihuItem()
            item['signature'] = "".join(userInfo1.findAll('span', attrs={'class':'bio'})[0].strings)
            item['yonghu'] = "".join(userInfo1.findAll('span', attrs={'class':'name'})[0].strings)
            ##这个我抓取的是他的用户名与签名。。。。虽说爬虫很小,但是思路最重要。
            print item['signature']
            print item['yonghu']
            return item


 zhihu/zhihu/items.py: 

from scrapy.item import Item, Field

class ZhihuItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    yonghu=scrapy.Field()
    signature=scrapy.Field()
    pass

然后scrapy crawl zhihuspider~~~~~~~~


ps:如果在item['signature']... list index out of range报错,说明

那个人的签名太长了..... :)..哈哈   

昨天考完46级。qusiba。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值