Scrapy爬虫 - 获取知乎用户数据

2023-05-16

2016-04-10

Scrapy爬虫 - 获取知乎用户数据

安装Scrapy爬虫框架

关于如何安装Python以及Scrapy框架,这里不做介绍,请自行网上搜索。

初始化

安装好Scrapy后,执行 scrapy startproject myspider
接下来你会看到 myspider 文件夹,目录结构如下:

  • scrapy.cfg

  • myspider

    • items.py

    • pipelines.py

    • settings.py

    • __init__.py

    • spiders

      • __init__.py

编写爬虫文件

在spiders目录下新建 users.py

# -*- coding: utf-8 -*-
import scrapy
import os
import time
from zhihu.items import UserItem
from zhihu.myconfig import UsersConfig # 爬虫配置

class UsersSpider(scrapy.Spider):
    name = 'users'
    domain = 'https://www.zhihu.com'
    login_url = 'https://www.zhihu.com/login/email'
    headers = {
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
        "Accept-Language": "zh-CN,zh;q=0.8",
        "Connection": "keep-alive",
        "Host": "www.zhihu.com",
        "Upgrade-Insecure-Requests": "1",
        "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36"
    }

    def __init__(self, url = None):
        self.user_url = url

    def start_requests(self):
        yield scrapy.Request(
            url = self.domain,
            headers = self.headers,
            meta = {
                'proxy': UsersConfig['proxy'],
                'cookiejar': 1
            },
            callback = self.request_captcha
        )

    def request_captcha(self, response):
        # 获取_xsrf值
        _xsrf = response.css('input[name="_xsrf"]::attr(value)').extract()[0]
        # 获取验证码地址
        captcha_url = 'http://www.zhihu.com/captcha.gif?r=' + str(time.time() * 1000)
        # 准备下载验证码
        yield scrapy.Request(
            url = captcha_url,
            headers = self.headers,
            meta = {
                'proxy': UsersConfig['proxy'],
                'cookiejar': response.meta['cookiejar'],
                '_xsrf': _xsrf
            },
            callback = self.download_captcha
        )

    def download_captcha(self, response):
        # 下载验证码
        with open('captcha.gif', 'wb') as fp:
            fp.write(response.body)
        # 用软件打开验证码图片
        os.system('start captcha.gif')
        # 输入验证码
        print 'Please enter captcha: '
        captcha = raw_input()

        yield scrapy.FormRequest(
            url = self.login_url,
            headers = self.headers,
            formdata = {
                'email': UsersConfig['email'],
                'password': UsersConfig['password'],
                '_xsrf': response.meta['_xsrf'],
                'remember_me': 'true',
                'captcha': captcha
            },
            meta = {
                'proxy': UsersConfig['proxy'],
                'cookiejar': response.meta['cookiejar']
            },
            callback = self.request_zhihu
        )

    def request_zhihu(self, response):
        yield scrapy.Request(
            url = self.user_url + '/about',
            headers = self.headers,
            meta = {
                'proxy': UsersConfig['proxy'],
                'cookiejar': response.meta['cookiejar'],
                'from': {
                    'sign': 'else',
                    'data': {}
                }
            },
            callback = self.user_item,
            dont_filter = True
        )

        yield scrapy.Request(
            url = self.user_url + '/followees',
            headers = self.headers,
            meta = {
                'proxy': UsersConfig['proxy'],
                'cookiejar': response.meta['cookiejar'],
                'from': {
                    'sign': 'else',
                    'data': {}
                }
            },
            callback = self.user_start,
            dont_filter = True
        )

        yield scrapy.Request(
            url = self.user_url + '/followers',
            headers = self.headers,
            meta = {
                'proxy': UsersConfig['proxy'],
                'cookiejar': response.meta['cookiejar'],
                'from': {
                    'sign': 'else',
                    'data': {}
                }
            },
            callback = self.user_start,
            dont_filter = True
        )

    def user_start(self, response):
        sel_root = response.xpath('//h2[@class="zm-list-content-title"]')
        # 判断关注列表是否为空
        if len(sel_root):
            for sel in sel_root:
                people_url = sel.xpath('a/@href').extract()[0]

                yield scrapy.Request(
                    url = people_url + '/about',
                    headers = self.headers,
                    meta = {
                        'proxy': UsersConfig['proxy'],
                        'cookiejar': response.meta['cookiejar'],
                        'from': {
                            'sign': 'else',
                            'data': {}
                        }
                    },
                    callback = self.user_item,
                    dont_filter = True
                )

                yield scrapy.Request(
                    url = people_url + '/followees',
                    headers = self.headers,
                    meta = {
                        'proxy': UsersConfig['proxy'],
                        'cookiejar': response.meta['cookiejar'],
                        'from': {
                            'sign': 'else',
                            'data': {}
                        }
                    },
                    callback = self.user_start,
                    dont_filter = True
                )

                yield scrapy.Request(
                    url = people_url + '/followers',
                    headers = self.headers,
                    meta = {
                        'proxy': UsersConfig['proxy'],
                        'cookiejar': response.meta['cookiejar'],
                        'from': {
                            'sign': 'else',
                            'data': {}
                        }
                    },
                    callback = self.user_start,
                    dont_filter = True
                )

    def user_item(self, response):
        def value(list):
            return list[0] if len(list) else ''

        sel = response.xpath('//div[@class="zm-profile-header ProfileCard"]')

        item = UserItem()
        item['url'] = response.url[:-6]
        item['name'] = sel.xpath('//a[@class="name"]/text()').extract()[0].encode('utf-8')
        item['bio'] = value(sel.xpath('//span[@class="bio"]/@title').extract()).encode('utf-8')
        item['location'] = value(sel.xpath('//span[contains(@class, "location")]/@title').extract()).encode('utf-8')
        item['business'] = value(sel.xpath('//span[contains(@class, "business")]/@title').extract()).encode('utf-8')
        item['gender'] = 0 if sel.xpath('//i[contains(@class, "icon-profile-female")]') else 1
        item['avatar'] = value(sel.xpath('//img[@class="Avatar Avatar--l"]/@src').extract())
        item['education'] = value(sel.xpath('//span[contains(@class, "education")]/@title').extract()).encode('utf-8')
        item['major'] = value(sel.xpath('//span[contains(@class, "education-extra")]/@title').extract()).encode('utf-8')
        item['employment'] = value(sel.xpath('//span[contains(@class, "employment")]/@title').extract()).encode('utf-8')
        item['position'] = value(sel.xpath('//span[contains(@class, "position")]/@title').extract()).encode('utf-8')
        item['content'] = value(sel.xpath('//span[@class="content"]/text()').extract()).strip().encode('utf-8')
        item['ask'] = int(sel.xpath('//div[contains(@class, "profile-navbar")]/a[2]/span[@class="num"]/text()').extract()[0])
        item['answer'] = int(sel.xpath('//div[contains(@class, "profile-navbar")]/a[3]/span[@class="num"]/text()').extract()[0])
        item['agree'] = int(sel.xpath('//span[@class="zm-profile-header-user-agree"]/strong/text()').extract()[0])
        item['thanks'] = int(sel.xpath('//span[@class="zm-profile-header-user-thanks"]/strong/text()').extract()[0])

        yield item

添加爬虫配置文件

在myspider目录下新建myconfig.py,并添加以下内容,将你的配置信息填入相应位置

# -*- coding: utf-8 -*-
UsersConfig = {
    # 代理
    'proxy': '',

    # 知乎用户名和密码
    'email': 'your email',
    'password': 'your password',
}

DbConfig = {
    # db config
    'user': 'db user',
    'passwd': 'db password',
    'db': 'db name',
    'host': 'db host',
}

修改items.py

# -*- coding: utf-8 -*-
import scrapy

class UserItem(scrapy.Item):
    # define the fields for your item here like:
    url = scrapy.Field()
    name = scrapy.Field()
    bio = scrapy.Field()
    location = scrapy.Field()
    business = scrapy.Field()
    gender = scrapy.Field()
    avatar = scrapy.Field()
    education = scrapy.Field()
    major = scrapy.Field()
    employment = scrapy.Field()
    position = scrapy.Field()
    content = scrapy.Field()
    ask = scrapy.Field()
    answer = scrapy.Field()
    agree = scrapy.Field()
    thanks = scrapy.Field()

将用户数据存入mysql数据库

修改pipelines.py

# -*- coding: utf-8 -*-
import MySQLdb
import datetime
from zhihu.myconfig import DbConfig

class UserPipeline(object):
    def __init__(self):
        self.conn = MySQLdb.connect(user = DbConfig['user'], passwd = DbConfig['passwd'], db = DbConfig['db'], host = DbConfig['host'], charset = 'utf8', use_unicode = True)
        self.cursor = self.conn.cursor()
        # 清空表
        # self.cursor.execute('truncate table weather;')
        # self.conn.commit()

    def process_item(self, item, spider):
        curTime = datetime.datetime.now()
        try:
            self.cursor.execute(
                """INSERT IGNORE INTO users (url, name, bio, location, business, gender, avatar, education, major, employment, position, content, ask, answer, agree, thanks, create_at)
                VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""",
                (
                    item['url'],
                    item['name'],
                    item['bio'],
                    item['location'],
                    item['business'],
                    item['gender'],
                    item['avatar'],
                    item['education'],
                    item['major'],
                    item['employment'],
                    item['position'],
                    item['content'],
                    item['ask'],
                    item['answer'],
                    item['agree'],
                    item['thanks'],
                    curTime
                )
            )
            self.conn.commit()
        except MySQLdb.Error, e:
            print 'Error %d %s' % (e.args[0], e.args[1])

        return item

修改settings.py

找到 ITEM_PIPELINES,改为:

ITEM_PIPELINES = {
   'myspider.pipelines.UserPipeline': 300,
}

在末尾添加,设置爬虫的深度

DEPTH_LIMIT=10

爬取知乎用户数据

确保MySQL已经打开,在项目根目录下打开终端,
执行 scrapy crawl users -a url=https://www.zhihu.com/people/<user>
其中user为爬虫的第一个用户,之后会根据该用户关注的人和被关注的人进行爬取数据
接下来会下载验证码图片,若未自动打开,请到根目录下打开 captcha.gif,在终端输入验证码
数据爬取Loading...

源码

源码可以在这里找到 github

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Scrapy爬虫 - 获取知乎用户数据 的相关文章

  • 安装 scrapy 清理失败

    我一直在努力得到Scrapy使用 pip 安装 以便抓取 NBA 赛季的赛程表和得分 在过去的 6 个小时里 我一直在努力尝试安装它 我已经逐字按照设置说明进行操作 但仍然无法使其正常工作 任何帮助将不胜感激 终端窗口输出如下 非常感谢 顺
  • 网页抓取中如何获取重定向的URL?

    我想要的只是请求实际 url 后重定向的 url 这是实际的网址https metric picodi net us r 19761 当我使用此 url 在浏览器上按 Enter 键时 它会将我重定向到这样的 url https www o
  • Scrapy:为什么提取的字符串是这种格式?

    我正在做 item desc site select a text extract 但这会像这样打印 u n A mano libera n 我必须做什么来添加和删除奇怪的字符 例如 u in 尾随空格和 我无法修剪 剥离 exceptio
  • scrapy-redis程序不会自动关闭

    scrapy redis框架 redis存储的xxx requests已经爬取完毕 但是程序还在运行 如何自动停止程序 而不是一直在运行 运行代码 2017 08 07 09 17 06 scrapy extensions logstats
  • Scrapy从div中获取href

    我开始在一个小项目中使用Scrapy 但无法提取链接 每次找到该类时 我只得到 而不是 url 我错过了一些明显的东西吗 sel Selector response for entry in sel xpath div class reci
  • Scrapy 遭遇 DEBUG:爬行(400)

    我正在尝试使用 Scrapy 抓取页面 https zhuanlan zhihu com wangzhenotes 我运行这个命令 scrapy shell https zhuanlan zhihu com wangzhenotes and
  • 如何使用google api抓取数据

    import requests def search query pages 4 rsz 8 url https ajax googleapis com ajax services search web params v 1 0 Versi
  • Scrapy 是否可以从原始 HTML 数据中获取纯文本?

    例如 scrapy shell http scrapy org content hxs select id content extract 0 print content 然后 我得到以下原始 HTML 代码 div h2 Welcome
  • 将 Tor 与 scrapy 框架结合使用

    我正在尝试抓取网站 该网站足够复杂以阻止机器人 我的意思是它只允许几个请求 之后 Scrapy 挂起 问题1 有没有办法 如果Scrapy挂起 我可以从同一点重新启动我的爬行过程 为了摆脱这个问题 我这样写了我的设置文件 BOT NAME
  • “download_slot”在 scrapy 中如何工作

    我在 scrapy 中创建了一个脚本来解析author name来自其着陆页的不同帖子 然后将其传递到parse page方法使用meta关键字以打印post content随着author name同时 我用过下载槽在元关键字中 据称该关
  • 从 Django 调用 Scrapy Spider

    我有一个项目 在同一工作区中包含 django 和 scrapy 文件夹 my project django project django project settings py app1 app2 manage py scrapy pro
  • Scrapy 阿拉伯字母返回一些奇怪的东西

    我在用scrapy关于阿拉伯字母和英文字母 英文字母完美地工作 然而 阿拉伯字母显示如下 gs300 2006 u0644 u0643 u0632 u0633 u062c u064a 有什么帮助吗 我正在使用 python 和 scrapy
  • 好斗的。开始爬行后如何更改蜘蛛设置?

    我无法更改解析方法中的蜘蛛设置 但这绝对是一个办法 例如 class SomeSpider BaseSpider name mySpider allowed domains example com start urls http examp
  • 抓取多个帐户,即多次登录

    我可以成功抓取单个帐户的数据 我想在一个网站上抓取多个帐户 这意味着多次登录 如何管理登录 注销 您可以在每个帐户会话中使用多个 cookiejar 并行抓取多个帐户 请参阅 cookiejar 请求元密钥http doc scrapy o
  • 在同一进程中多次运行Scrapy

    我有一个网址列表 我想抓取其中的每一个 请注意 将此数组添加为start urls不是我正在寻找的行为 我希望它在单独的爬网会话中一一运行 我想在同一个进程中多次运行Scrapy 我想将 Scrapy 作为脚本运行 如常见做法 https
  • 如何使用scrapy Selector获取节点的innerHTML?

    假设有一些 html 片段 例如 a text in a b text in b b a
  • 错误:尝试使用 scrappy 登录时出现 raise ValueError("No element found in %s" % response)

    问题描述 我想从我大学的bbs上抓取一些信息 这是地址 http bbs byr cn http bbs byr cn下面是我的蜘蛛的代码 from lxml import etree import scrapy try from scra
  • 我的扩展中未收到 Scrapy Spider_idle 信号

    我在几个蜘蛛之间有共同的行为spider idle正在接收信号 我想将此行为移至扩展中 我的分机已经监听spider opened and spider closed信号成功 但是 那spider idle未收到信号 这是我的扩展 为简洁起
  • 如何使用scrapy检查网站是否支持http、htts和www前缀

    我正在使用 scrapy 来检查某些网站是否工作正常 当我使用http example com https example com or http www example com 当我创建 scrapy 请求时 它工作正常 例如 在我的pa
  • XPath:通过当前节点属性选择当前和下一个节点的文本

    首先 这是从我之前的问题 https stackoverflow com questions 5202187 xpath select current and next nodes text by current node attribut

随机推荐

  • matlab练习程序(获取鼠标坐标)

    还是一个函数的使用ginput clear all close all clc img 61 ones 200 200 imshow img x y 61 ginput 这里鼠标左键点击一次 x y 添加一个值 xff0c 点四次就有四个值
  • 收到了免费的Visual Studio 2005 EE

    昨天 xff0c 收到了Micorsoft寄来的MSDN开发精选 xff08 5 xff09 xff0c 其中就包含了SQL Server 2005 Express Edition和Visual c 2005 EE xff0c xff0c
  • H3C交换机SNMP配置详解

    H3C交换机SNMP配置 1 启动 关闭SNMP Agent服务 在系统视图模式下 xff1a 启用 xff1a snmp agent 关闭 xff1a undo snmp agent 注 xff1a 缺省情况下snmp agent是关闭的
  • ppp的chap认证完全配置

    网络环境 xff1a CHAP认证命令 xff1a cisco config interface s0 0 cisco config if encapsulation ppp cisco config if ppp authenticati
  • MAVLink认识、使用、自定义

    对mavlink的认识 MAVLink是针对小型飞行器 xff08 MAV xff09 的一个lightweight header only message marshalling library 由头文件构成的信息编组库 它被封装成C结构
  • WHY数学图形可视化工具(开源)

    WHY数学图形可视化工具 软件下载地址 http files cnblogs com WhyEngine WhyMathGraph zip 源码下载地址 http pan baidu com s 1jG9QKq6 软件的开发语言是C 43
  • docker学习笔记16:Dockerfile 指令 ADD 和 COPY介绍

    一 ADD指令 ADD指令的功能是将主机构建环境 xff08 上下文 xff09 目录中的文件和目录 以及一个URL标记的文件 拷贝到镜像中 其格式是 xff1a ADD 源路径 目标路径 如 xff1a test FROM ubuntu
  • 无限“递归”的python程序

    如果一个函数直接或者间接调用了自己 xff0c 那么就形成了递归 xff08 recursion xff09 xff0c 比如斐波那契数列的一个实现 def fib n if n lt 61 2 return 1 else return f
  • FreeRTOS 二值信号量,互斥信号量,递归互斥信号量

    以下转载自安富莱电子 xff1a http forum armfly com forum php 本章节讲解 FreeRTOS 任务间的同步和资源共享机制 xff0c 二值信号量 二值信号量是计数信号量的一种特殊形式 xff0c 即共享资源
  • 替代vnc图像远程工具NOMACHINE

    最近再做关于oracle rac集群的实验 难免要在图像界面下进行操作 以前都用的是vnc 但是vnc貌似比较占资源而已图像质量不是很好 今天无意发现了一个替代VNC的好工具NOMACHINE 它的官方网址是 http www nomach
  • antd-design LocaleProvider国际化

    1 LocaleProvider 使用 React 的 context 特性 xff0c 只需在应用外围包裹一次即可全局生效 import LocaleProvider from 39 antd 39 import zh CN from 3
  • python 读取文件、并以十六进制的方式写入到新文件

    usr bin env python infile 61 file 34 in mp3 34 34 rb 34 outfile 61 file 34 out txt 34 34 wb 34 def main while 1 c 61 inf
  • perl的内置函数scalar

    scalar可以求数组的长度 xff0c 但是 xff0c 在scalar的说明里面并没有这一项 Forces EXPR to be interpreted in scalar context and returns the value o
  • sqlalchemy批量删除数据、全量删除

    问题 xff1a sqlalchemy如何批量删除多条数据 解决 xff1a 使用参数synchronize session 61 False xff0c 或for循环 方法 xff1a users 61 self db query Use
  • 经典的同态滤波算法的优化及其应用参数配置。

    同态滤波 xff0c 网络上有很多文章提到过这个算法 xff0c 我们摘取百度的一段文字简要的说明了该算法的核心 xff1a 同态滤波是一种减少低频增加高频 xff0c 从而减少光照变化并锐化边缘或细节的图像滤波方法 关于该算法 xff0c
  • Trajectory following with MAVROS OFFBOARD on Raspberry Pi

    原文链接 Trajectory following with MAVROS OFFBOARD on Raspberry Pi Jaeyoung Lim August 10 2016 404warehouse Small Projects B
  • 职位介绍 之 嵌入式开发工程师

    笔者电子信息专业硕士毕业 xff0c 获得过多次电子设计大赛 大学生智能车 数学建模国奖 xff0c 现就职于南京某半导体芯片公司 xff0c 从事硬件研发 xff0c 电路设计研究 对于学电子的小伙伴 xff0c 深知入门的不易 xff0
  • Elementui el-dialog 组件我又学会了一种新的用法

    1 新建弹窗Form vue文件 将visible属性设置为true lt template gt lt div gt lt el dialog title 61 34 提示 34 visible 61 34 true 34 width 6
  • webpack系列——实现一个行内样式px转vw的loader

    需求 自从有了postcss来处理css文件 xff0c 我们可以快速进行网站适配的开发 xff0c 只需要改改参数 xff0c 样式按照设计稿的px写 xff0c webpack编译自动转换成rem或者vw等 但是 xff0c 标签内的p
  • Scrapy爬虫 - 获取知乎用户数据

    2016 04 10 Scrapy爬虫 获取知乎用户数据 安装Scrapy爬虫框架 关于如何安装Python以及Scrapy框架 xff0c 这里不做介绍 xff0c 请自行网上搜索 初始化 安装好Scrapy后 xff0c 执行 scra