目录

一、xpath

1.xpath_helper

2.xpath语法

xpath中的节点关系

表达式

zip函数

二、腾讯课堂评论案例

三、mysql数据库


一、xpath

1.xpath_helper

我们上节讲到 json 格式的数据使用 jsonpath 进行数据的提取,同时我们可以使用 网站:json.cn 使json格式的数据结构更加清晰,方便我们提取

那这节我们要讲另一个非常重要的格式的数据提取:html。html 格式的数据我们通常使用 xpath 进行数据提取,同时介绍一个工具:xpath_helper,他与解析json格式数据使用的网站作用类似,可以方便我们解析html格式的数据。

我已经将xpath_helper的压缩包上传到了我的资源中,供大家免费使用。在下载完压缩包后解压到当前文件夹,会得到一个 xpath-helper.crx 的文件,我们打开Google浏览器,点击右上角的 “三个点” 的按键,点击更多工具中的扩展程序,然后将 xpath-helper.crx 直接拖进Google浏览器,最后重启浏览器。检查时候安装成功:点击右上角 “三个点” 旁边有个像拼图的按键,找到Xpath Helper,然后点击,如果出现两个黑窗口说明已经安装成功(或者使用快捷键ctrl + shift + X)。

2.xpath语法

json > 第三方库jsonpath执行提取json格式的语法

html > 第三方库lxml执行提取html格式的语法(xpath)

xpath中的节点关系

表达式

表达式 描述
nodename 选中该元素。
/ 从根节点选取、或者是元素和元素间的过渡。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。
text() 选取文本。

实例

在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

路径表达式 结果
bookstore 选择bookstore元素。
/bookstore 选取根元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。
//book 选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//book/title/@lang 选择所有的book下面的title中的lang属性的值。
//book/title/text() 选择所有的book下面的title的文本。

接下来我们听过豆瓣电影top250的页面来练习上述语法:https://movie.douban.com/top250

鼠标右键点击检查,选择Network,刷新页面,找到top250数据包

需求:获取电影名称和对应详情页的url

经确认top250数据包是html格式的,我们在top250的response中使用快捷键:ctrl + F 输入肖申克的救赎,然后就可以发现电影名和他们详情页的url是存在html数据中的,在检查其他电影发现他们的电影名称和详情页的url也是存在html数据中。

我们要想从top250的数据包中提取到电影名和详情页的url,首先要获得html数据。

import requests
from fake_useragent import FakeUserAgentif __name__ == '__main__':# 1.确认目标的urlurl_ = 'https://movie.douban.com/top250'# 构造请求头headers_ = {'User-Agent': FakeUserAgent().random}# 2.发送请求,获取响应数据response_ = requests.get(url_, headers=headers_)data_ = response_.textprint(data_)

上面的代码执行后,data_ 就是我们需要的html数据。html格式数据的提取需要执行xpath语法,在此以前我们需要确认想要提取的数据,并确认xpath语法的有效性(利用xpath_helper)

<div class="info"><div class="hd"><a href="https://movie.douban.com/subject/1292052/" class=""><span class="title">肖申克的救赎</span><span class="title">&nbsp;/&nbsp;The Shawshank Redemption</span><span class="other">&nbsp;/&nbsp;月黑高飞(港)  /  刺激1995(台)</span></a>

注意:

1.在html中,例如:<span class="title">肖申克的救赎</span>,<x> </x>总是成对出现

2. <x>文本数据</x>

xpath_helper的构造:左边写xpath语法,右边显示对应的结果

jsonpath一般从根节点开始定位,xpath一般不从根节点开始(由于html语言格式的问题)。

我们需要提取的是电影的名称,我们发现他在<span class="title">和</span>之间,所以是文本数据,需要使用 text() 提取,同时我们还需要定位到<span class="title">,因为他是属于span标签的

//span/text()

直接跨节点找到span标签的文本数据,根据xpath_helper的反馈,有292个结果,可是这个页面中只有25个电影,即25个电影名称,292远远多于25,所以我们要进行过滤操作

过滤方法:

1.根据属性        <span class="title">肖申克的救赎</span>,class="title"就是这个标签的属性

2.根据父节点        从下面的代码可以看出:a标签就是class属性为title的span标签的父节点

<a href="https://movie.douban.com/subject/1292052/" class=""><span class="title">肖申克的救赎</span>

 3.同级标签,标签名相同,属性也相同时,我们可以使用索引。(xpath语法的索引从1开始)

通过上述过滤方法,我们可以确定最后的xpath语法:

//a/span[@class='title'][1]/text()

之后,我们使用第三方库 lxml ,执行xpath语法

import requests
from fake_useragent import FakeUserAgent
from lxml import etreeif __name__ == '__main__':# 1.确认目标的urlurl_ = 'https://movie.douban.com/top250'# 构造请求头headers_ = {'User-Agent': FakeUserAgent().random}# 2.发送请求,获取响应数据response_ = requests.get(url_, headers=headers_)data_ = response_.text# print(data_)# 3.数据的提取# (1).转换格式 > xpath语法不能直接操作python格式的字符串html_obj = etree.HTML(data_)title_list = html_obj.xpath("//a/span[@class='title'][1]/text()")# print(title_list)

需要注意的是: xpath的提取结果和jsonpath一样都是一个列表

 详情页url的提取:

<div class="info"><div class="hd"><a href="https://movie.douban.com/subject/1292052/" class=""><span class="title">肖申克的救赎</span><span class="title">&nbsp;/&nbsp;The Shawshank Redemption</span><span class="other">&nbsp;/&nbsp;月黑高飞(港)  /  刺激1995(台)</span></a>

对应的xpath语法:

//div[@class='hd']/a/@href
import requests
from fake_useragent import FakeUserAgent
from lxml import etreeif __name__ == '__main__':# 1.确认目标的urlurl_ = 'https://movie.douban.com/top250'# 构造请求头headers_ = {'User-Agent': FakeUserAgent().random}# 2.发送请求,获取响应数据response_ = requests.get(url_, headers=headers_)data_ = response_.text# print(data_)# 3.数据的提取# (1).转换格式 > xpath语法不能直接操作python格式的字符串html_obj = etree.HTML(data_)title_list = html_obj.xpath("//a/span[@class='title'][1]/text()")# print(title_list)url_list = html_obj.xpath("//div[@class='hd']/a/@href")# print(url_list)# 4.保存(略)

zip函数

list1 = ['a', 'b']
list2 = [1, 2]
dict_ = dict(zip(list1, list2))
print(dict_)    # {'a': 1, 'b': 2}

我们可以看到zip函数第一个参数是作为 键名 的列表,第二个参数是作为 值 的列表

二、腾讯课堂评论案例

我们以https://ke.qq.com/course/425893为例,在我们点击评论后,加载的数据包并不包含评论信息,只有当我们点击了评论中的全部评论后才会出现对应的数据包(即找到了对应的url),查看preview,我们发现数据包的数据是json格式的

import requests
from fake_useragent import FakeUserAgentif __name__ == '__main__':# 1.确认目标的urlurl_ = 'https://ke.qq.com/cgi-bin/comment_new/course_comment_list?cid=425893&count=10&page=0&filter_rating=0&bkn=260593302&r=0.7131207274398879'# 构造请求头headers_ = {'User-Agent': FakeUserAgent().random,'Cookie': 'RK=3PptZAXHNG; ptcz=0a8ee31077f15dbc8b652bcded52e5312ba6f1b50b3851fed841a642536aecb1; pgv_pvi=5472699392; pgv_pvid=8009771513; ts_uid=1386988748; ke_login_type=1; localInterest=[2032]; o_cookie=925290303; pac_uid=1_925290303; eas_sid=41q6x140H584g9Q6d4J7a3i2h1; sd_userid=2251615169031575; sd_cookie_crttime=1615169031575; tvfe_boss_uuid=7fff752b6f976d19; _pathcode=0.19297139008784892; tdw_auin_data=-; iswebp=1; tdw_first_visited=1; Hm_lvt_0c196c536f609d373a16d246a117fd44=1625421010; pgv_info=ssid=s9590420085; ts_refer=www.baidu.com/link; _qpsvr_localtk=0.27361930633804943; tdw_data_sessionid=162542108087646589378986; ts_last=ke.qq.com/course/425893; tdw_data_testid=; tdw_data_flowid=; uin=o0925290303; skey=@fqMi4eMJj; luin=o0925290303; lskey=00010000195df01b242ea1cb526d55f181749e7edaaae9577a5d84257c6935afb38c518e98e47db7e9a3bb5b; pt4_token=Zr4JcDZb5qs1YDNLXOGa4k6qHPTbAQe5rO6Gw*os93g_; p_skey=iBermNfAdmxG8oOK*bxmD7Zo88CLhPJ4An0rXaBMZFI_; p_lskey=000400009c4d0d1b69f4dc95614b9786a332a0f6020edd1812cd2f119238f14c961b449b5a595a48d4487f5b; auth_version=2.0; mix_login_mode=true; uid_type=0; uin=925290303; p_uin=925290303; p_luin=925290303; uid_uin=925290303; uid_origin_uid_type=0; tdw_data={"ver4":"www.baidu.com","ver5":"","ver6":"","refer":"www.baidu.com","from_channel":"","path":"ddddh-0.19297139008784892","auin":"-","uin":925290303,"real_uin":"25290303"}; sessionPath=1625421258802847841718; Hm_lpvt_0c196c536f609d373a16d246a117fd44=1625421259; tdw_data_new_2={"auin":"-","sourcetype":"","sourcefrom":"","uin":925290303,"visitor_id":"1765771903493909","sessionPath":"1625421258802847841718","ver9":925290303}'}# 2.发送请求,获取响应数据response_ = requests.get(url_, headers=headers_)data_ = response_.json()print(data_)    # {'msg': 'refer错误', 'type': 1, 'retcode': 100101}

我们按照平常的流程发送请求,获取响应数据,发现并没有成功,并且告诉我们是refer错误(跳转错误)

为什么会检查我们的跳转信息呢?

答案是:这是一种反爬手段。打个比方,去动物园要检查你是否买票,买了票从大门进入的是正常游客,翻墙进入动物园的不是正常游客。有了跳转信息就相当于有了门票,你就是一个正常的访问者,而我们的爬虫程序因为没有带上跳转信息,被查出来不是正常访问者,所以拒绝我们进行访问

如何快速检测一个url是否需要Referer跳转信息呢?

复制url直接在浏览器空白页面打开,如果访问成功就说明不需要Referer跳转信息,访问失败说明需要Referer跳转信息

解决办法:加上Referer跳转信息

因为要爬取全部评论信息,所以肯定需要翻页操作,通过查看第一页,第二页评论的url,我们发现url中只有page和r的值不一样,我们把r的值删掉发现依旧可以成功访问网站,所以r是一个没用的参数。然后就是page,第一页page的值是0,第二页page的值是1以此类推,这就是翻页url的规律

"""
翻页的url的规律
1.https://ke.qq.com/cgi-bin/comment_new/course_comment_list?cid=425893&count=10&page=0&filter_rating=0&bkn=260593302&r=0.7131207274398879
2.https://ke.qq.com/cgi-bin/comment_new/course_comment_list?cid=425893&count=10&page=1&filter_rating=0&bkn=260593302&r=0.5652967797600523
3.https://ke.qq.com/cgi-bin/comment_new/course_comment_list?cid=425893&count=10&page=2&filter_rating=0&bkn=260593302&r=0.35105405427203641.page: 0
2.page: 1
3.page: 2
另一个变化的参数r 没关系
"""import requests
import jsonpath
import json
from fake_useragent import FakeUserAgent
import timeif __name__ == '__main__':for i in range(3):# 1.url的确认url_ = f'https://ke.qq.com/cgi-bin/comment_new/course_comment_list?cid=425893&count=10&page={i}&filter_rating=0&bkn=260593302&r=0.3510540542720364'# 设置一个用户代理headers_ = {'User-Agent': FakeUserAgent().random,'Cookie': 'RK=3PptZAXHNG; ptcz=0a8ee31077f15dbc8b652bcded52e5312ba6f1b50b3851fed841a642536aecb1; pgv_pvi=5472699392; pgv_pvid=8009771513; ts_uid=1386988748; ke_login_type=1; localInterest=[2032]; o_cookie=925290303; pac_uid=1_925290303; eas_sid=41q6x140H584g9Q6d4J7a3i2h1; sd_userid=2251615169031575; sd_cookie_crttime=1615169031575; tvfe_boss_uuid=7fff752b6f976d19; _pathcode=0.19297139008784892; tdw_auin_data=-; iswebp=1; tdw_first_visited=1; Hm_lvt_0c196c536f609d373a16d246a117fd44=1625421010; pgv_info=ssid=s9590420085; ts_refer=www.baidu.com/link; _qpsvr_localtk=0.27361930633804943; tdw_data_sessionid=162542108087646589378986; ts_last=ke.qq.com/course/425893; tdw_data_testid=; tdw_data_flowid=; uin=o0925290303; skey=@fqMi4eMJj; luin=o0925290303; lskey=00010000195df01b242ea1cb526d55f181749e7edaaae9577a5d84257c6935afb38c518e98e47db7e9a3bb5b; pt4_token=Zr4JcDZb5qs1YDNLXOGa4k6qHPTbAQe5rO6Gw*os93g_; p_skey=iBermNfAdmxG8oOK*bxmD7Zo88CLhPJ4An0rXaBMZFI_; p_lskey=000400009c4d0d1b69f4dc95614b9786a332a0f6020edd1812cd2f119238f14c961b449b5a595a48d4487f5b; auth_version=2.0; mix_login_mode=true; uid_type=0; uin=925290303; p_uin=925290303; p_luin=925290303; uid_uin=925290303; uid_origin_uid_type=0; tdw_data={"ver4":"www.baidu.com","ver5":"","ver6":"","refer":"www.baidu.com","from_channel":"","path":"ddddh-0.19297139008784892","auin":"-","uin":925290303,"real_uin":"25290303"}; sessionPath=1625421258802847841718; Hm_lpvt_0c196c536f609d373a16d246a117fd44=1625422801; tdw_data_new_2={"auin":"-","sourcetype":"","sourcefrom":"","uin":925290303,"visitor_id":"1765771903493909","sessionPath":"1625421258802847841718","ver9":925290303}; report_position_key={"url_position":"","url_module":"","url_page":"course"}','Referer': 'https://ke.qq.com/course/425893'  # 从正规的页面跳转过来的}# 2.发送网络请求, 获取响应对象response_ = requests.get(url_, headers=headers_)data_ = response_.json()  # 自动转换python格式的数据# print(data_)# 3.解析数据 > json类型的数据# 昵称name_list = jsonpath.jsonpath(data_, '$..nick_name')# 评论comment_list = jsonpath.jsonpath(data_, '$..first_comment')# print(name_list)# print(comment_list)# 4.保存,本地for i in range(len(name_list)):dict_ = {}dict_[name_list[i]] = comment_list[i]json_data = json.dumps(dict_, ensure_ascii=False) + ',\n'with open('腾讯课堂翻页评论q.json', 'a', encoding='utf-8') as f:f.write(json_data)# 降低请求频率,避免被反爬time.sleep(1.5)

三、mysql数据库

类似的东西:txt文件,excel表格

数据库:增、删、改、查

数据库的优点:保存海量数据,数据提取更加迅速,读取速度快,可以放在云服务器上

分类:关系型数据库:数据表彼此之间是有关系的(mysql)

非关系型数据库:数据表之间是没有关系的(redis)

操作:

1.打开虚拟机,模拟云端(云服务器)

-- 确定我们的电脑能够访问到云服务器

-- 查看本机的IP地址:cmd任务栏输入:ipconfig

-- 虚拟机:ping我们本机的IP地址  ping xxx.xxx.xxx.xxx

已经确认可以连接到云服务器

2.mysql配置文件,默认是规定了只接受来自本地IP的访问

-- 虚拟机先切换路径:cd/etc/mysql/mysql.con.f

-- sudo vim mqsqld.cnf

-- 找到bind-address,按i进入编辑模式,把bind_address修改成0.0.0.0(任意IP)

-- 按esc进入命令模式

-- 按shift + :进入末行模式

-- 输入wq,回车,保存退出

3.mysql数据库默认只有本地用户root去修改里面的数据

-- 把默认只允许本地用户root操作 改成 允许任意用户修改

-- 进入mysql数据库

-- cd~ 回到最原始的路径

-- mysql -u用户名 -p数据库密码

-- show databases; 查看有多少个数据库(文件夹)

-- 修改mysql数据库里面的配置数据

-- 选择mysql数据库(文件夹) >  use mysql;

-- 进入mysql同名数据库之后

-- 可以查看里面有多少个数据表(文件)>  show tables;

-- 我们需要使用修改user这个数据表

-- 查看这个user数据表里面的数据  > select * from user;展示user数据表的所有内容)

select Host,User from user;展示user数据表的部分内容)

-- 将看到 localhost root  >  但是只有本地(localhost)的用户才能够去进行访问

-- update user set Host=’%‘ where User=’root‘;当user数据表里面的User值为root的时候,就把对应的Host值改成%

这三步修改完之后,我们的本机windows就可以往云服务器(虚拟机)的mysql数据库写入数据了

需要注意的是:sql语言末尾需要加上 分号;

Python爬虫(第五周)相关推荐

  1. Python爬虫进阶五之多线程的用法

    前言 我们之前写的爬虫都是单个线程的?这怎么够?一旦一个地方卡到不动了,那不就永远等待下去了?为此我们可以使用多线程或者多进程来处理. 首先声明一点! 多线程和多进程是不一样的!一个是 thread ...

  2. Python爬虫入门五之URLError异常处理

    Python爬虫入门五之URLError异常处理 参考文章: (1)Python爬虫入门五之URLError异常处理 (2)https://www.cnblogs.com/pxuan/p/647362 ...

  3. python爬虫练习五(补充): 2018年统计用区划代码和城乡划分代码(附代码与全部数据)

    之前爬取过2017年的数据 详见 Python爬虫练习五:爬取 2017年统计用区划代码和城乡划分代码(附代码与全部数据) ,下面有评论说广东省的数据缺少了东莞与中山两个市的数据,检查网页结构发现确实 ...

  4. 浅谈Python爬虫(五)【网易云热评爬取实例】

    浅谈Python爬虫(五) 目的:爬取网易云歌单所有歌曲的信息及热评 Python环境:3.7 编译器:PyCharm2019.1.3专业版 存储格式:JSON 1.分析网页 进入网易云音乐首页,点击 ...

  5. python爬虫(五):博客spider

    针对爬虫首先声明只是玩具pc,拿到自己博客地址,然后随机访问,最后增加TamperMonkey插件 python爬虫 思想很简单,包含了2个类IPSpyder和CSDN类,前者保证一周内get一次ip ...

  6. Python爬虫利器五Selenium用法

    在上一节我们学习了 PhantomJS 的基本用法,归根结底它是一个没有界面的浏览器,而且运行的是 JavaScript 脚本,然而这就能写爬虫了吗?这又和 Python 有什么关系?说好的 Pyth ...

  7. python爬虫(五)------pyquery库(一)------attr()、text()、html()、addClass()、hasClass()、removeattr()等方法

    python爬虫(四)------bs4库(二)------BeautifulSoup的findall().find(().select()和select_one()等方法 pyquery库 安装 p ...

  8. Python 爬虫(五):PyQuery 框架

    目录 1 准备工作 1.1 安装 1.2 初始化 2 快速上手 2.1 基本使用 2.2 伪类选择器 PyQuery 是仿照 jQuery 实现的,语法与 jQuery 几乎完全相同,如果你熟悉 jQ ...

  9. python爬虫笔记五:汽车之家贴吧信息(字体反爬-动态映射)

    学习网址: https://jia666666.blog.csdn.net/article/details/108974149 ----------------------------------- ...

  10. Python 爬虫进阶五之多线程的用法

    我们之前写的爬虫都是单个线程的?这怎么够?一旦一个地方卡到不动了,那不就永远等待下去了?为此我们可以使用多线程或者多进程来处理. 首先声明一点! 多线程和多进程是不一样的!一个是 thread 库,一 ...

最新文章

  1. Android电影票座位几排几列 数据获取
  2. 在页面中控制媒体流的起播点和播放长度
  3. 替换空格---StringBuilder
  4. UVa 11624,两次BFS
  5. Android 多进程调试技巧
  6. Nginx系列~负载均衡服务器与WWW服务器的实现
  7. RHEL6.3配置文件共享(5) Samba服务之三
  8. 图解VC++2012编译安装GDAL1.11.0和入门例子
  9. Python | numpy | np.split()与np.array_split()函数
  10. 猪和兔子的玻璃体给人用(仅仅是个人想法)
  11. iOS 二叉树相关算法实现
  12. Spring 3.1,Cloud Foundry和本地开发
  13. 2022年中国即时配送行业趋势研究报告
  14. 一键生成安卓证书_【带壳截图+电影台词 生成器】
  15. 摩托罗拉再裁员!仍坚守模块化手机业务
  16. Spring AOP失效之谜
  17. 如何通过网页方式将jar包上传到nexus?
  18. 由于应用程序配置不正确,应用程序未能启动 VS2008 Release /MD编译
  19. 计算机审计 pdf,巧学计算机审计.pdf
  20. GitHub项目精选

热门文章

  1. 其实你孤独的像一只流浪狗
  2. RN导入高德地图定位的用法实例
  3. SmartGit功能介绍
  4. 为什么宝宝做错事被骂哭后,还要求抱抱?
  5. Multi-Tenancy模式,基础服务大规模扩张的时候,是应该推进了。
  6. vim的安装以及基础使用方法;
  7. 《手把手教你移植InfoNES(到HANKER-LM4F232)》
  8. 做表情包就能卖1亿刀,这事儿放在国内我是不信的
  9. matlab中仿真中接地,基于Matlab的配电网接地故障仿真
  10. 我又来分享来了,发现一个好的ide,免费的国产的,优秀的,自带md阅读器.那就是uni-app