qq纵横四海源码_【0基础】纵横中文网python爬虫实战

8de667ed8665088e5280ebd65e8ea04e.png

原文在此~

【0基础】纵横中文网python爬虫实战​mp.weixin.qq.com
cb9be8d6e1f925c8727ae1896bcc823f.png

大家好,我是你们的机房老哥!

在粉丝群的日常交流中,爬虫是比较常见的话题。python最强大的功能之一也是爬虫。

考虑到很多0基础的小白想要入门爬虫。老哥今天就通过一个比较简单的爬虫,介绍一下python爬虫的流程及思路,并扫盲爬虫常用工具的语法。

本次教程您将学到:

  • 爬虫思路、流程
  • xpath全解析
  • css选择器全解析
  • requests_html库进阶

4621fab36ae36a20448f7dc0bacaf118.png
▲最终成果

话不多说,接下来就是:

-STUDY PYTHON WITH-

基础教程——纵横中文python爬虫

-OLDER BROTHER-

获取小说信息

http://book.zongheng.com/store.html

06e1ce34e3861d46807180ed2875e8b0.png
▲纵横中文网

要爬取的网址如上图所示。

导入老哥最常用的爬虫库requests_html库,首先将HTMLSession()函数定义为session。使用session.get()命令提交响应,最后打印r.html.html查看网页源代码。

from requests_html import HTMLSessionsession = HTMLSession()
url = 'http://book.zongheng.com/store.html'
r = session.get(url)
print(r.html.html)

25617a6ee9ab61b36b47bddbc0b5d440.png
▲打印网页源码

如上图所示,老哥已经成功获得网页源码了。说明网站的反爬手段比较弱,适合新手练习。

ec3d1fa896f84aa98af8e70ef26ae74e.png
▲分析网址结构

按F12打开控制台,可以看到左侧小说的信息在<div class="bookbox fl" </div>下,右侧小说的信息在<div class="bookbox fr" </div>下。网址结构非常简单。

ec3d1fa896f84aa98af8e70ef26ae74e.png
▲分析小说名称

我们点入每个小说信息的div下,获取小说的信息。

可以看到,<div class="bookname">标签下的a标签中,href是小说网址,内容是小说标题。

<div class="booklink">标签下的第一个a标签中,href是作者的介绍页网址,内容是作者笔名。第二个a标签中,href是小说分类主题页网址,内容是小说分类。第一个span中是小说连载状态,第二个span中是小说更新时间。

接下来通过xpath分别提取这些信息,代码如下:

bookname = r.html.xpath('//div[@class="bookname"]/a/text()')
bookname_links = r.html.xpath('//div[@class="bookname"]/a/@href')
authorname = r.html.xpath('//div[@class="bookilnk"]/a/text()')
author_links = r.html.xpath('//div[@class="bookilnk"]/a/@href')
typename = r.html.xpath('//div[@class="bookilnk"]/a[2]/text()')
type_links = r.html.xpath('//div[@class="bookilnk"]/a[2]/@href')
status = r.html.xpath('//div[@class="bookilnk"]/span/text()')
time_ = r.html.xpath('//div[@class="bookilnk"]/span[2]/text()')
for num in range(len(bookname_links)):print(bookname[num], bookname_links[num], authorname[num], author_links[num], typename[num], type_links[num],status[num].strip(), time_[num].strip())

解析上述代码:通过r.html.xpath调用库中自带的xpath语法提取小说名。//div代表任意位置的div标签,[@class="bookname"]是xpath语法,中括号中@符号后是div的属性,这里用div的标签class="bookname"定位到小说名称。/a代表这个div下的第一个a标签,最后用text()函数提取a标签内容,即小说标题。

提取网址方法类似,区别在于在a标签后接/@href提取a标签下的href属性。

当一个div标签下有两个a标签时,a[2]代表第二个a标签。

3a9b2d0034c126ca817b9efb0581f81c.png
▲获取小说信息

这里顺便扫盲一下xpath的基础语法:

详解xpath

选取节点:

  • xpath('/div')——从根节点上选取div节点。
  • xpath('//div')——选取所有div节点。
  • xpath('./div')——选取当前节点下的div节点。
  • xpath('../a')——选取当前的父节点下的第一个a节点。

谓语:

  1. xpath('/body/div[1]') ——选取body下的第一个div节点。
  2. xpath('/body/div[last()]')——选取body下的最后一个div节点。
  3. xpath('/body/div[last()-1]')——选取body下的倒数第2个div节点。
  4. xpath('/body/div[positon()<3]')——选取body下的前2个div节点。
  5. xpath('/body/div[@class]')——选取body下带有class属性的div节点。
  6. xpath('/body/div[@class="main"]')——选取body下class属性为main的div节点。
  7. xpath('/body/div[price>35.00]')——选取body下price元素值大于35的div节点。
  8. xpath('/div/*')——选取div下的所有子节点。
  9. xpath('/div[@*]')——选取所有带属性的div节点。
  10. xpath('/div/node()')——匹配div下任何类型的节点。
  11. xpath('//div|//table')——选择所有div和table节点。

功能函数:

  • xpath('//div[starts-with(@id,"ma")]')——选取id值以ma开头的div节点。
  • xpath('//div[contains(@id,"ma")]')——选取id值包含ma的div节点。
  • xpath('//div[contains(@id,"ma") and contains(@id,"in")]')——选取id值包含ma和in的div节点。
  • xpath('//div[contains(text(),"ma")]')——选取文本中包含ma的节点。

在这里老哥在稍微拓展一下。获得小说链接,除了上文中的方式,还可以用如下代码:

bookname_links = r.html.xpath('//div[@class="bookname"]/a', first=True)
print(bookname_links.attrs['href'])

解析一下上述代码,使用first=True提取div下的第一个a标签。在这里用.attrs['href']命令提取a标签下的href属性,同样可以得到链接。

值得注意的是,first=True提取的是第一个标签,返回element格式。如果不加,则返回列表格式,就不能使用该方法了。

620eeceb5e5c2f82c2a74eb8b7022605.png
▲方法2获得href下的链接
▲方法2获得href下的链接

进入小说内容页

上文中已经提取到小说的链接,我们只需要再次用session.get()命令请求这个链接,即可得到小说内容。

9c448860cda1863d7b40f48dba9f9272.png
▲小说详情页

不过,上文中提出的链接点进去是小说详情页,所以想要获取小说内容,还需要提取“开始阅读”对应的href链接。代码如下:

bookname_links = r.html.xpath('//div[@class="bookname"]/a/@href')
for num in range(len(bookname_links)):bookname_link = bookname_links[num]r = session.get(bookname_link)r2 = r.html.xpath('//div[contains(@class,"btn-group")]/child::a')[0].linksprint(r2)

解析上述代码:老哥为了拓展教程,用了第三种方式提取链接。首先解析xpath语法,//div[contains(@class,"btn-group")],代表获取包含"btn-group"的class属性的div节点。这种方式的好处在于,假如该div节点的class有很多,写起来比较复杂,就可以用contains获取该class中包含的某个唯一字段。/child::a代表该div下的第一个子节点a。

由于这种方式得到的是一个列表,提取列表的第一个值,该值包含小说链接。这个值是<class 'requests_html.Element'>类型,这种类型是requests_html库自带的类型,可以使用.links命令提取该requests_html.Element下的所有链接。因为本案例只有一个链接,所以就返回一个值,即小说的链接。

上述代码中的r2即小说内容页的链接。

进阶:requests_html的.links命令

为了更好的理解.links命令的强大之处,老哥附带一个小案例。例如用.links命令提取根网站下的所有网址,代码如下:

from requests_html import HTMLSession
session = HTMLSession()
url = 'http://book.zongheng.com/store.html'
r = session.get(url)
print(r.html.links)

025687559e08e01a71c1473a509bcb6d.png
▲轻松获取所有链接

可以看到,如果请求的网址下有很多网址,用.links命令可以不费吹灰之力的得到他们。

有时一些链接只有后半部分,需要拼接网站的域名才能使用,这时候,只需要将.links改成.absolute_links,即可获得自动补全的所有链接。

小说内容提取

最后一步就是小说内容提取,方法和上文类似,就不赘述了。这个网站有趣的地方在于禁止左键、右键点击。如果不会爬虫,只会复制粘贴网页信息的话,就会被难住了。当然用爬虫就完全无视这种“小伎俩”啦。

aadba746803dc4d95951acb3c18795a7.png
▲小说内容
▲小说内容

这部分和上文类似,解析标题、内容所在位置,为了拓展教程,老哥这里使用css选择器。代码如下:

r3 = session.get(list(r2)[0])
title = r3.html.find('.title_txtbox', first=True).text
author = r3.html.find('.bookinfo', first=True).text
content = r3.html.find('.content', first=True).text

解析上述代码,r3.html.find()代表使用css选择器。.title_txtbox代表选择class为title_txtbox的值,.是css选择器中选择class类型的符号。最后用.text命令获取内容,类似.links命令。

扫盲一下css选择器的基础语法:

详解CSS选择器

  • .intro——选择class="intro"的所有元素。
  • #firstname——选择id="firstname"的所有元素。
  • *——选择所有元素。
  • p——选择所有<p>元素。
  • div,p——选择所有<div>元素和所有<p>元素。
  • divp——选择<div>元素内部的所有<p>元素。
  • div>p——选择父元素为<div>元素的所有<p>元素。
  • div+p——选择紧接在<div>元素之后的所有<p>元素。
  • [target]——选择带有target属性所有元素。
  • [target=_blank]——选择target="_blank"的所有元素。
  • [title~=flower]——选择title属性包含单词"flower"的所有元素。
  • [lang|=en]——选择lang属性值以"en"开头的所有元素。
  • a:link——选择所有未被访问的链接。
  • a:visited——选择所有已被访问的链接。
  • a:active——选择活动链接。
  • a:hover——选择鼠标指针位于其上的链接。
  • input:focus——选择获得焦点的input元素。
  • p:first-letter——选择每个<p>元素的首字母。
  • p:first-line——选择每个<p>元素的首行。
  • p:first-child——选择属于父元素的第一个子元素的每个<p>元素。
  • p:before——在每个<p>元素的内容之前插入内容。
  • p:after——在每个<p>元素的内容之后插入内容。
  • p:lang(it)——选择带有以"it"开头的lang属性值的每个<p>元素。
  • p~ul——选择前面有<p>元素的每个<ul>元素。
  • a[src^="https"]——选择其src属性值以"https"开头的每个<a>元素。
  • a[src$=".pdf"]——选择其src属性以".pdf"结尾的所有<a>元素。
  • a[src*="abc"]——选择其src属性中包含"abc"子串的每个<a>元素。
  • p:first-of-type——选择属于其父元素的首个<p>元素的每个<p>元素。
  • p:last-of-type——选择属于其父元素的最后<p>元素的每个<p>元素。
  • p:only-of-type——选择属于其父元素唯一的<p>元素的每个<p>元素。
  • p:only-child——选择属于其父元素的唯一子元素的每个<p>元素。
  • p:nth-child(2)——选择属于其父元素的第二个子元素的每个<p>元素。
  • p:nth-last-child(2)——同上,从最后一个子元素开始计数。
  • p:nth-of-type(2)——选择属于其父元素第二个<p>元素的每个<p>元素。
  • p:nth-last-of-type(2)——同上,但是从最后一个子元素开始计数。
  • p:last-child——选择属于其父元素最后一个子元素每个<p>元素。
  • :root——选择文档的根元素。
  • p:empty——选择没有子元素的每个<p>元素(包括文本节点)。
  • #news:target——选择当前活动的#news元素。
  • input:enabled——选择每个启用的<input>元素。
  • input:disabled——选择每个禁用的<input>元素
  • input:checked——选择每个被选中的<input>元素。
  • :not(p)——选择非<p>元素的每个元素。
  • ::selection——选择被用户选取的元素部分。

翻页

568bbc00ab6a55aea1fcb796f587fe96.png
▲翻页

这里涉及到翻页,因为小说只有下一页,没有具体页数,所以只能循环读取下一页来不停的获取小说内容。

nextchapter = list(r3.html.find('.nextchapter', first=True).links)[0]

获取到下一页网址后,写一个循环来获取下一页,直到无法获取,则爬取完一本小说的所有内容。

for i in range(100000):try:name = session.get(nextchapter)title = name.html.find('.title_txtbox', first=True).textauthor = name.html.find('.bookinfo', first=True).textcontent = name.html.find('.content', first=True).textnextchapter = list(name.html.find('.nextchapter', first=True).links)[0]print(title,'n', content)except:break

解析上述代码,设定一个极大的值,让程序不断循环,获取每页的小说,直到最后一页,无法获取小说内容时,break跳出循环,并开启一本新的小说的爬取。

4621fab36ae36a20448f7dc0bacaf118.png
▲爬到的小说内容

欣赏一下最终的成果吧!

这样一个基础爬虫教程就结束了,是不是很简单呢!

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

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

相关文章

Eigen(3)矩阵Matrix及其简单操作

1. Matrix类 在Eigen&#xff0c;所有的矩阵和向量都是Matrix模板类的对象&#xff0c;Vector只是一种特殊的矩阵&#xff08;一行或者一列&#xff09;。 Matrix有6个模板参数&#xff0c;主要使用前三个参数&#xff0c;剩下的有默认值。 Matrix<typename Scalar, int Ro…

java jquery_jQuery数据表和Java集成

java jqueryjQuery DataTables是一个开放源代码插件&#xff0c;用于在浏览器中创建表。 它具有许多功能&#xff0c;例如排序&#xff0c;服务器端处理&#xff0c; JQUERY UI主题滚动。 该插件的下载链接&#xff1a; http://www.datatables.net/download/ 在本演示中&am…

Eigen(2) 模块与头文件

Eigen库被分为一个Core模块和其他一些模块&#xff0c;每个模块有一些相应的头文件。 为了便于引用&#xff0c;Dense模块整合了一系列模块&#xff1b;Eigen模块整合了所有模块。一般情况下&#xff0c;include<Eigen/Dense> 就够了

白鹭龙骨异步加载

private armatureDisplay: dragonBones.EgretArmatureDisplay; /** * 加载龙骨动画 * Create scene interface */ private loadGragon(): void { let t this; t.removeGragon(); //默认男战士 let sex t.occupationSex.selectedValue ? t.occupationSex.selectedValue : 1; …

zip和unzip上的Java要点

压缩是编写文件时可以在我们的代码中发出的主要动作之一。 因此&#xff0c;我发现在zip和unzip上必不可少的简单Java代码段&#xff0c;并且必须易于访问。 要点是纯Java语言&#xff0c;并以zip格式存储两个文件。 完成后&#xff0c;打开打开的拉链并评估其内容。 import …

ppt图片丢失_041 职场PPT实战:做好的PPT换个电脑就丢字体?三招解决!

大家好&#xff0c;我是肥宅。这是《职场PPT实战》系列更文的第41篇。本期我要跟大家聊一个很实在的问题&#xff0c;字体嵌入。有小伙伴在后台提问&#xff0c;他是这么说的&#xff1a;“肥宅老师&#xff0c;我做好的PPT&#xff0c;换个电脑打开字体就变了&#xff0c;有没…

matlab sort对矩阵某一维进行排序并记录之前索引

sort函数默认升序排列&#xff0c;即‘ascend’&#xff1b; [B, index] sort(A&#xff0c;dim&#xff0c; model) B为排序后矩阵 index记录排序前的索引号 A需要进行排序操作的矩阵 dim对矩阵的维度&#xff08;一维不用指定&#xff0c;二维默认对列&#xff09; mode…

2018-2019-2 20165221 【网络对抗技术】-- Exp9 Web安全基础

2018-2019-2 20165221 【网络对抗技术】-- Exp9 Web安全基础 目录&#xff1a; 一 . 实验要求二 . 实验过程记录 1 . Webgoat安装2 . SQL注入的攻击 命令注入&#xff08;Command Injection&#xff09;数字型注入&#xff08;Numeric SQL Injection&#xff09;日志欺骗&#…

python不同目录调用_python3 不同目录间模块调用

#Author by Andy#_*_ coding:utf-8 _*_#__file__获取当前程序的相对路径import os,sys#print(__file__)# os.path.abspath(__file__) 获取当前程序的绝对路径print(os.path.abspath(__file__))# E:\my python study\day4\Atm\bin\atm.pyPathos.path.abspath(__file__)# print(o…

python 安装虚拟环境virtualenv

1.sudo apt install virtualenv 安装失败 2.sudo apt-get update 更新失败 提示&#xff1a; E: 仓库 “http://mirrors.aliyun.com/ubuntu artful Release” 不再含有 Release 文件。N: 无法安全地用该源进行更新&#xff0c;所以默认禁用该源。N: 参见 apt-secure(8) 手册以了…

python内存管理_Python内存管理(一):预备知识

一、内存的理解你可以将计算机中的内存理解为一本为短期存储而设计的书。这本书中现在什么都没写&#xff0c;但最终不同的“作者”会来寻求空间&#xff0c;写入他们想写的故事。由于他们之间不能彼此覆盖&#xff0c;他们在开始写入之前一定要向这本书的管理者申请&#xff0…

javacv 人脸检测_使用JavaCV进行手和手指检测

javacv 人脸检测这篇文章是Andrew Davison博士发布的有关自然用户界面&#xff08;NUI&#xff09;系列的一部分&#xff0c;内容涉及使用JavaCV从网络摄像头视频提要中检测手。 注意&#xff1a;本章的所有源代码都可以从http://fivedots.coe.psu.ac.th/~ad/jg/nui055/下载。…

vector赋值的常见错误

易范错误1&#xff1a; vector<int> a; for (int i 0; i<10; i) a[i] i; //这种做法以及类似的做法都是错误的。下标只能用于获取已存在的元素&#xff0c;而现在的a[i]还是空的对象 正确做法1&#xff1a; vector<int> a; for (int i 0; i<10; i) a&…

python的pandas库中如何计算每列出现最多的值_Python Pandas中根据列的值选取多行数据...

Pandas中根据列的值选取多行数据# 选取等于某些值的行记录 用 df.loc[df[column_name] some_value]# 选取某列是否是某一类型的数值 用 isindf.loc[df[column_name].isin(some_values)]# 多种条件的选取 用 &df.loc[(df[column] some_value) & df[other_column].isin…

补码运算。

一.补码加法。 先求出两个数的补码。补码相加。最后的结果为补码&#xff0c;若要取得真值需再次求补。超过模的进位需丢掉。二.补码减法。 三.溢出检测 转载于:https://www.cnblogs.com/Ravenzzz/p/10930014.html

Oracle JDK 9 Early Access文档已更新

Raymond Gallardo在2017年4月4日发布的针对Oracle JDK 9的抢先体验文档 已更新&#xff0c;今天宣布对Oracle JDK9文档的抢先体验页面进行了更新。 Gallardo重点介绍了一些更新的部分&#xff0c;包括Oracle JDK 9的新增功能 &#xff0c; Oracle JDK 9迁移指南 &#xff0c; H…

python 读取当前文件夹下所有后缀为.lib文件

# -*- coding: utf-8 -*-import os def file_name(file_dir):for root, dirs, files in os.walk(file_dir):#print(root) # 当前目录路径#print(dirs) # 当前路径下所有子目录print(files) # 当前路径下所有非目录子文件file_name(file_dir) #输出当前文件夹下所有后缀为.li…

python分割字符串输出_python字符串分割

内置split()函数 str.split(sepNone, maxsplit-1)sep为自定义分割符&#xff0c;maxsplit为最大分割次数&#xff0c;默认值-1进行全部分割注意以下区别&#xff1a;str.split() 以空格分割&#xff0c;包括连续空格str.split( ) 同样以空格分割&#xff0c;但是不能识别连续空…

python requests 10041报错_Python-Requests1-批量登录获取uid

需求&#xff1a;从表格取不同的手机号和密码登录&#xff0c;获取不同用户的信息&#xff0c;写入本地表格requests官网&#xff1a;https://github.com/requests/requests1、安装Requests模块1、官网下载requests包2、解压&#xff0c;命令行进入python目录&#xff0c;运行安…

pdf保存如何带批注_带有批注的SpringSelenium测试

pdf保存如何带批注这篇文章描述了如何在Java中实现Selenium测试。 它的灵感来自Alex Collins的帖子&#xff0c;并带有注释。 该代码可在GitHub的Spring-Selenium-Test目录中找到。 一些替代方法和更轻巧的技术可用于对Spring MVC应用程序进行单元测试。 要进行单元测试服务&am…