简书搜索爬虫

这期的爬虫是爬取“简书”的搜索结果页,篇幅将会分为两部分来写,第一部分是爬虫部分,主要涉及搜索文章的提取和数据保存,第二部分涉及基本的数据分析和可视化,本篇文章属于爬虫篇。

爬虫源代码

首先看一下整个爬虫的源代码,每个函数的用处已经写在函数说明中,后面也会进行代码解读。

# -*- coding: utf-8 -*-
import requests
import json
from urllib.parse import quote
from pymongo import MongoClient"""
简书搜索爬虫
输入搜索关键词,将搜索到的所有文章爬取下来
数据保存到 mongodb 中
"""class JianshuSearch(object):def __init__(self, db_name, coll_name, key, host='127.0.0.1', port=27017):self.headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/57.0.2987.110 Safari/537.36"}self.url = 'http://www.jianshu.com/search/do?q={key}&type=note&page={page}&order_by=default'self.key = quote(key)self.start_page = 1self.host = hostself.port = portself.db_name = db_nameself.coll_name = coll_namedef get_total_pages(self):'''提取总页码数'''url = self.url.format(key=self.key, page=self.start_page)html = requests.get(url, headers=self.headers).textdata = json.loads(html)total_pages = data['total_pages']return total_pagesdef get_infos(self, page):'''提取单个页面的文章信息,格式为dict'''url = self.url.format(key=self.key, page=page)html = requests.get(url, headers=self.headers).textdata = json.loads(html)entries = data['entries']for each in entries:self.save_infos(each)def save_infos(self, entry):'''保存一个文章的信息'''coon = MongoClient(host=self.host, port=self.port)coll = coon[self.db_name][self.coll_name]coll.insert(entry)def main(self):'''主函数,循环迭代进行翻页,提取所有页码的信息并保存到数据库'''total_pages = int(self.get_total_pages())for i in range(1, total_pages + 1):self.get_infos(i)print('总计{}页,已经爬完{}页'.format(total_pages, i))if __name__ == '__main__':DB_NAME = 'jianshu'COLL_NAME = 'search_result'key = 'python'spider = JianshuSearch(key=key, db_name=DB_NAME, coll_name=COLL_NAME)spider.main()

爬虫思路

基本思路

爬虫的基本思路依然分为3个主要步骤:

  1. 找到入口,即起始页面的 URL
  2. 找到翻页的规律
  3. 选择有效的方式进行翻页,提取所有信息

查看页面主要信息

首先在简书的搜索框中输入任意一个关键词,例如“Python”,然后点击搜索按钮,查看结果页面。

结果页面如下图所示:

搜索结果

可以看到,搜索的结果包含了很多种类的信息,有“相关用户”、“相关专题”和“相关文章”,并且文章的排序还可以选择条件。

由于这里只需要提取搜索文章的信息,因此可以先看一下搜索到的文章列表中包含哪些可以收集的信息,以便后续查找和保存数据。

找到入口——第一个 URL

当然,一般来说,很多时候,我们看到的信息其实并不是眼前的页面给我们的信息,而是当前页面从其他地方“搬”过来的信息。如果使用或者知道ajax 的用法,这句话就很好理解,当然,不理解也无妨,并不影响后续操作。

打开浏览器的开发者界面,可以使用快捷键 F12。刷新一下搜索的页面,然后进入 Network,看看浏览器中加载了什么页面。

一般可以先从 Doc中查看,也就是网页源代码,但是这次的爬虫可以看到源代码中并没有搜索的结果页,于是可以继续查看 js,发现好像也没有新加载页面,继续查看 XHR,终于找到了刷新页面加载出来的页面请求,具体看截图:

请求

看截图中的编号,编号1就是页面加载的地方,编号2可以看到请求的 URL,编号3就是 URL 的组成,可以从中查看链接的构成规律,这里的规律就是链接中有2个关键参数,第一个参数就是搜索的关键词,这里用 q=Python表示,然后第二个参数就是当前页码,这里是 page=2,从这里就可以直接联想到,如果知道总页码数,那就可以使用循环来得到所有页码的 URL。编号4是请求的方式,这里是 GET。

选择翻页方式

经过这个页面,就可以把整个爬虫的思路理清楚了:

  • 首先,想办法找到总页码数
  • 然后提取单页的信息,并且保存到数据库中
  • 使用循环方式,提取所有页的信息

源码解读

首先需要导入相关库:

import requests
import json
from urllib.parse import quote
from pymongo import MongoClient

这4个库的作用分别是:

  1. 网页请求
  2. 将字符串格式转换成 json 格式
  3. 将一般字符串转换成 URL 可以读取的格式
  4. python 连接 mongodb 的依赖

爬虫类的创建

由于这个爬虫是创建了一个爬虫类,所以需要按照 Python类的规范来,首先初始化类,通过函数来实现:

def __init__(self, db_name, coll_name, key, host='127.0.0.1', port=27017):self.headers = {"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ""Chrome/57.0.2987.110 Safari/537.36"}self.url = 'http://www.jianshu.com/search/do?q={key}&type=note&page={page}&order_by=default'self.key = quote(key)self.start_page = 1self.host = hostself.port = portself.db_name = db_nameself.coll_name = coll_name

这里给类传递了5个参数,其中3个是没有给予默认值的参数,2个是给了默认值的参数,每个参数的含义:

  • key:搜索的关键词
  • db_name:数据库名称
  • coll_name:数据表名称
  • host,port:链接数据库的地址和端口

提取总页码数

可以通过爬取任意一个页码,然后打印一下提取的信息,看看信息的构成。

通过打印信息可以发现,每个页面的信息都是一个字典格式,因此可以通过json模块来转换成 Python 的 dict 格式,然后可以发现每页都有一个参数是“total_pages”,这个参数就提供了当前搜索的结果总页码数,因此可以通过函数来提取这个参数的值:

def get_total_pages(self):'''提取总页码数'''url = self.url.format(key=self.key, page=self.start_page)html = requests.get(url, headers=self.headers).textdata = json.loads(html)total_pages = data['total_pages']return total_pages

提取当个页面的信息,并保存到数据库

由于每个页面的信息都是一个 json 格式,所以信息的提取方式很简单,直接从字典中提取就行了:

def get_infos(self, page):'''提取单个页面的文章信息,格式为dict'''url = self.url.format(key=self.key, page=page)html = requests.get(url, headers=self.headers).textdata = json.loads(html)entries = data['entries']for each in entries:self.save_infos(each)

函数的思路很简单,首先通过 requests 请求网页,然后得到一个json类型的信息,但是由于这个信息的格式是 str, 所以需要使用 json.loads 方法转换成 dict 格式。然后使用字典的键值对关系提取到总页码数就可以了。

这个函数的最后面用到了一个保存信息的函数,也就是后面要说的将数据保存到数据库中。

def save_infos(self, entry):'''保存一个文章的信息'''coon = MongoClient(host=self.host, port=self.port)coll = coon[self.db_name][self.coll_name]coll.insert(entry)

保存到数据库的函数需要传入一个参数,是一个 dict 类型,这个参数正好可以理解为提取的单个文章的信息。

首先,按照 mongodb 的连接方式建立一个连接,这个连接就使用到了创建类的时候传入的数据库的参数,然后使用 insert()方法就可以插入数据了。

循环提取所有页面的信息

讲过上述的的函数,已经可以提取总页码数,也可以提取并保存单个页码的文章信息了,剩下的就是使用循环来提取所有页码的信息了,于是,可以把这个过程写到一个主函数中:

def main(self):'''主函数,循环迭代进行翻页,提取所有页码的信息并保存到数据库'''total_pages = int(self.get_total_pages())for i in range(1, total_pages + 1):self.get_infos(i)print('总计{}页,已经爬完{}页'.format(total_pages, i))

为了方便查看爬虫的进度,在每爬取一页信息,可以打印当前的进度。

运行爬虫

最后一段代码就是运行爬虫,首先给定一些需要传递到爬虫类中的参数,然后启动爬虫的主程序即可看到爬虫结果。

查看数据库中信息

“Python”这个字段在简书中有100页的数据(如果没有猜错,这个100页应该是简书默认提供的最大页码数),所以爬虫运行的时间并不长,爬完之后可以使用可视化工具看看数据库中的信息。

数据库中信息如图:

数据库

后记:从数据库中可以查看到一些有效信息,包括文字的标题、链接、发布时间、作者的信息、评论数、阅览量、喜欢数等。虽然这些数据并没有什么研究价值,但是本着练手的想法,后续会使用 Python 基本的数据分析工具来对爬取的信息进行可视化分析。

查看原文

转载于:https://www.cnblogs.com/gopythoner/p/7760548.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/415429.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

js的加密和解密

最近在研究js的加密和解密的问题,上网上搜出来很多方法,不过不知道到底哪一个会比较管用。这里是今天找到的一些关于base64加密解密的js代码,已经经过试验,可以使用,不过网上很多加密解密的工具,这种方式加…

TCP/IP协议三次握手与四次握手流程解析

一、TCP报文格式TCP/IP协议的详细信息参看《TCP/IP协议详解》三卷本。下面是TCP报文格式图:图1 TCP报文格式上图中有几个字段需要重点介绍下:(1)序号:Seq序号,占32位,用来标识从TCP源端向目的端…

Hadoop学习笔记—20.网站日志分析项目案例(三)统计分析

网站日志分析项目案例(一)项目介绍:http://www.cnblogs.com/edisonchou/p/4449082.html 网站日志分析项目案例(二)数据清洗:http://www.cnblogs.com/edisonchou/p/4458219.html 网站日志分析项目案例&#…

Jmeter使用流程及简单分析监控

一、安装Jmeter 1、下载Jmeter 下载地址:http://jmeter.apache.org/download_jmeter.cgi 目前最新版为2.9,其余文件如源代码等也可从如下官网下载: http://jmeter.apache.org/download_jmeter.cgi 2、安装Jmeter之前 安装Jmeter之前需要先配置…

JMeter工具使用初探

工欲善其事必先利其器,要保证移动应用产品在上线之后能稳定运行于各种复杂环境,仅仅进行功能测试是远远不够的,压力测试越来越被应用开发商所重视。而压力测试从传统的内部压力到基于云计算的压力测试,再到用户视角的外部压测&…

HDU1251 统计难题 trie树 简单

http://acm.hdu.edu.cn/showproblem.php?pid1251题意: 找前缀数量 裸模板 1 #include<cstdio>2 #include<cstring>3 #include<iostream>4 #include<algorithm>5 #include<cmath>6 #include<queue>7 using namespace std;8 const int maxn…

JMeter场景设置与监控

随着IT技术的飞速发展和企业互联网业务规模不断扩张&#xff0c;IT架构经历了以数据计算为核心的C/S架构、以聚焦业务功能及服务化构建应用的经典互联网架构和如今整合IT资源和按需使用的云计算架构三个阶段。 与之同步发展的压力测试同样有三个发展阶段&#xff0c;从防火墙内…

阿里云轻应用服务器 宝塔面板 mongodb 配置外网连接 其一 基础配置

买了一台阿里云轻应用服务器做测试&#xff0c;我默认安装的是宝塔面板&#xff0c;下面详细记录配置mongodb过程。 1、进行安装&#xff0c;通过宝塔面板自带的软件管理进行安装 2、首先需要保证外网能够进行访问 设置监听端口为0.0.0.0&#xff0c;原来的是127.0.0.1只允许…

工作151:初始登录样式

<!--GY歌谣控制登录页面的功能--> <template><div class"main"><div><h1> <img src"./geyao.png" style"width: 29px;height: 29px;margin-right: 10px;line-height: 29px" alt"">星传经管系统&l…

Dubbo超时机制导致的雪崩连接

Bug影响&#xff1a;Dubbo服务提供者出现无法获取Dubbo服务处理线程异常&#xff0c;后端DB爆出拿不到数据库连接池&#xff0c;导致前端响应时间异常飙高&#xff0c;系统处理能力下降&#xff0c;核心基础服务无法提供正常服务。 ​Bug发现过程&#xff1a; ​线 上&#xff…

云智慧压测实战分享之JMeter脚本录制实例

在前面的《云智慧压测实战分享之JMeter工具使用初探》中我们对JMeter的功能特点和常用元件做了简单介绍&#xff0c;接下来说说JMeter的脚本录制。JMeter有多种录制脚本方法&#xff0c;其中最常见的是通过第三方工具Badboy录制&#xff0c;另外还有JMeter自身设置(Http代理服务…

阿里云轻应用服务器 宝塔面板 mongodb 配置外网连接 其二 配置账号密码

其一的设置&#xff0c;不需要通过账号密码&#xff0c;就能直接访问数据库&#xff0c;安全性堪忧&#xff0c;我之前就踩过坑&#xff0c;也在之前的文章中讲过&#xff0c;这次用阿里云轻应用服务器重新介绍一波。 命令行窗口可以直接通过阿里云轻应用服务器里面自带的。 1、…

各种Span设置

备注&#xff1a;各种Span设置 &#xff08;转自http://blog.csdn.net/harvic880925/article/details/38984705 &#xff09; 在前面的一个小示例&#xff0c;大家应该也可以看出&#xff0c;要应用一个Span总共分三步&#xff1a; 1、构造String 2、构造Span 3、利用SetSpan…

工作152:阅读之后台管理登录样式

<template><div class"login-wrap"><div class"ms-login"><div class"ms-title">后台管理系统</div><el-form :model"param" :rules"rules" ref"login" label-width"0px&q…

div中图片下方有边距

遇到一个小问题&#xff0c;记录一下。 1、问题描述 <div class"thumb-box"><img class"tt-img" src"https://cdn.w7.cc/images/2017/11/09/15102068385a03ed7644fbf_OxLCy7ypXKpd.png?imageView2/5/w/88/h/88/format/png" alt"…

sign check fail: check Sign and Data Fail!-错误处理

一、报这个错大多都是支付宝公钥配置错误&#xff0c;不同环境的公钥是不同的&#xff0c;大家先确认自己的支付宝公钥获取是否正确:1. 沙箱公钥【查看】创建应用可参照&#xff1a;【如何创建应用】打开应用查看mapi网关适用于【 移动支付 】&#xff0c;【 老版手机网站支付 …

Android 事件分发,分发机制

1. 基础认知 1.1 事件分发的对象是谁&#xff1f; 答&#xff1a;点击事件&#xff08;Touch事件&#xff09; 定义 当用户触摸屏幕时&#xff08;View 或 ViewGroup派生的控件&#xff09;&#xff0c;将产生点击事件&#xff08;Touch事件&#xff09;Touch事件的相关细节…

工作154:代码之解析position 解决

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>日常请假</title><style>* {margin: 0px…