DataWhale 组队学习爬虫 Task2
任务描述:
2.1 学习beautifulsoup
学习beautifulsoup,并使用beautifulsoup提取内容。
使用beautifulsoup提取丁香园论坛的回复内容。
丁香园直通点:http://www.dxy.cn/bbs/thread/626626#626626 。
参考资料:https://blog.csdn.net/wwq114/article/details/88085875
2.2学习xpath
学习xpath,使用lxml+xpath提取内容。
使用xpath提取丁香园论坛的回复内容。
丁香园直通点:http://www.dxy.cn/bbs/thread/626626#626626 。
参考资料:https://blog.csdn.net/naonao77/article/details/8812999
--------------------------------------------------这是不怎么华丽的分割线-------------------------------------------------
声明一下:本文是为了学习爬虫,因此以下的内容可能是跟着以上链接中的教程操作一遍,有与原文相同的部分,该部分的版权归原作者所有。若有错误,请朋友指正。
1. 学习beautifulsoup
一、Beautifulsoup是一个包,将前面获取到的html编码变成一个树状的结构。 HTML页面的代码其实就是一个树状的结构:
最开始是<!DOCTYPE html>
并列往下<html lang="zh-cn">
在往下:<head></head>。 head之中就会开始有树形的结构标签,比如有<style><\style>,<meta><\meta>,然后style中又有其他。
head并列往下就会有<>body<\body>, body中有多个div,div中又有其他比如标签,比如td,tr,a。
二、获取到html的信息后,导入beautifulsoup包,使用find函数再去获取需要的内容。
find函数用法:
find(name, attrs, recursive, text, **wargs) # recursive 递归的,循环的
这些参数相当于过滤器一样可以进行筛选处理。不同的参数过滤可以应用到以下情况:
查找标签,基于name参数
查找标签的属性,基于attrs参数
查找文本,基于text参数
基于正则表达式的查找
基于函数的查找
代码实现:
使用urllib.request获取html
from urllib import requesturl = 'http://www.dxy.cn/bbs/thread/626626' headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0'} req = request.Request(url=url, headers=headers) res = request.urlopen(req).read() print(res.decode('utf-8')) #打印时要转码with open('dxy.html', 'wb') as f:f.write(res) #写入文件时,不要转码
返回的打印内容及保存的dxy.html文件,文件大小69k。
注意:这里遇到一个问题,就是python中用print打印出来时,需要decode('utf-8'),保存成html文件时,不要转码,直接用read()的结果写入。
使用beautifulsoup的find函数获取标签内容
从流浪器网页f12后,可以看到用户名在div class='auth'中(图一),评论内容在td class='postbody'中(图二),而每一段评论的所有内容都包含在一个tbody中,其实往上一层,是包含在一个div中(图三)。
因此教程里面用一个findall,找到所有的tbody,其实用findall找div也可以,但比较浪费资源
找到所有的tbody后,就开始找具体的名字和评论内容,找不到则要跳过,因此用一个try功能实现。
图一:⬇
图二:⬇
图三:⬇
代码实现:
from bs4 import BeautifulSoup as bs html = bs(res,'lxml')datas = [] #用来获取所有遍历到的结果 for data in html.find_all("tbody"):try:username = data.find("div", class_="auth").get_text(strip=True)print(username)content = data.find('td', class_='postbody').get_text(strip=True)print(content)datas.append((username,content)) #内层的括号,将每一个结果的子结果组合起来except:pass # 找不到就pass,因为findall找到的tbody中,可能没有对应的auth和postbody,上面tbody换成div也是可以的!print(datas)
由以上代码可以看到:
findall返回的结果是tboday的内容,findall返回的多个符合条件的结果,可以用一个for循环每一个结果,每一个结果又可以用find函数把对应的标签内容找到。
返回的结果:
2. 学习xpath
Xpath - 用于确定XML文档中某部分位置的语言。
XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。
- XPath 用“/”来作为上下层级间的分隔,第一个“/”表示文档的根节点<html></html>
- 定位某一个HTML标签,可以用
绝对路径:如 page_content.xpath(u"/html/body/p"),找到body下的所有p表情
或
相对路径:如 page_content.xpath(u"//p"),找到整个html中的所有p标签 - 添加过滤条件:
page_content.xpath(u"//p[@style='font-size: 200%']") # 标签属性中有style='font-size: 200%
page_content.xpath(u"//p[text() = 'hello']") #标签的文本内容包含'hello'
page_content.xpath(u"//div/ul/li[position() = 2]") #所有div中ul的第二个li标签,可简化为...li[2]
数字定位和过滤条件的顺序:
ul/li[5][@name='hello'] - ul第五个li,且name='hello',否则返回空
ul/li[@name='hello'][5] - ul下,第五个name为hello的标签,否则返回空 通配符 * 可以代替所有的节点名,/html/body/*/span 代表body下的所有span标签
descendant:: 代表任意多层的中间节点,可以省略成一个 /
/descendant::div[@id='leftmenu'] 或 //div[@id='leftmenu'] 所有id为leftmenu的divpage.xpath(u"/descendant::*[text()]")
表示任意多层的中间节点(相同的节点)下任意标签之间的内容,也即实现蜘蛛抓取页面内容功能。- 不同节点之间的内容获取 (假如需要获取"
取不到的内容
"这几个字,该怎么做的?)
xpath(u"//div[tail='<br />']") # 失败.....:(
xpath(u"/body/div[tail]") # 失败.....:(<div class="news">1. <b>无流量站点清理公告</b> 2013-02-22<br/>取不到的内容 </div> <div class="news"> 2. <strong>无流量站点清理公告</strong> 2013-02-22<br />取不到的内容 </div> <div class="news"> 3. <span>无流量站点清理公告</span> 2013-02-22<br />取不到的内容 </div>
following-sibling:: 同一层的下一个节点
使用模块 lxml.html.clean 的一个Cleaner 类来清理 HTML 页
支持删除嵌入或脚本内容、 特殊标记、 CSS 样式注释或者更多
cleaner = Cleaner(style=True, scripts=True,page_structure=False, safe_attrs_only=False)
# 注意,page_structure,safe_attrs_only为False时保证页面的完整性,否则,这个Cleaner会把你的html结构与标签里的属性都给清理了。
print(cleaner.clean_html(html))- 忽略大小写可以:
page = etree.HTML(html)
keyword_tag = page.xpath("//meta[translate(@name,'ABCDEFGHJIKLMNOPQRSTUVWXYZ', 'abcdefghjiklmnopqrstuvwxyz')='keywords']")
语法格式:
from lxml import etree:
html_document = ''' HTML 文档 '''
tree = etree.HTML(html_document.lower().decode('utf-8')) # 需要用utf-8解码
elements = page_content.xpath(u"//标签") # 根目录下的所有a标签元素
for element in elements :
print(element.attrib) # 打印标签的属性
print(element.text) # 打印标签的内容
使用lxml前注意事项:先确保html经过了utf-8解码,即code = html.decode('utf-8', 'ignore'),否则会出现解析出错情况。因为中文被编码成utf-8之后变成 '/u2541' 之类的形式,lxml一遇到 “/”就会认为其标签结束。
参考别人的例子:
html_document=''' <html><head><meta name="content-type" content="text/html; charset=utf-8" /><title>友情链接查询 - 站长工具</title><!-- uRj0Ak8VLEPhjWhg3m9z4EjXJwc --><meta name="Keywords" content="友情链接查询" /><meta name="Description" content="友情链接查询" /></head><body><h1 class="heading">Top News</h1><p style="font-size: 200%">World News only on this page</p>Ah, and here's some more text, by the way.<p>... and this is a parsed fragment ...</p><a href="http://www.cydf.org.cn/" rel="nofollow" target="_blank">青少年发展基金会</a><a href="http://www.4399.com/flash/32979.htm" target="_blank">洛克王国</a><a href="http://www.4399.com/flash/35538.htm" target="_blank">奥拉星</a><a href="http://game.3533.com/game/" target="_blank">手机游戏</a><a href="http://game.3533.com/tupian/" target="_blank">手机壁纸</a><a href="http://www.4399.com/" target="_blank">4399小游戏</a><a href="http://www.91wan.com/" target="_blank">91wan游戏</a></body> </html> '''from lxml import etree tree= etree.HTML(html_document.lower()) # page_content = etree.HTML(html_document.lower().decode('utf-8)) # 这里使用decode('utf-8')出错了,string类型只有encode()属性? # 或许是因为文本已经是解码过的 # 尝试改为page_content = etree.HTML(html_document.lower().encode('utf-8)), # 反而没报错但出现乱码 elements = tree.xpath(u"//a") for element in elements:print(element.attrib) #打印出来是字典类型print(element.text) #打印出来是文本类型print('--'*20)
返回:
注意:
page_content = etree.HTML(html_document.lower().decode('utf-8)),这里面的decode需要根据前面的对象使用,上面举的例子用文本,文本没有decode('utf-8)的属性.....
element.attrib 结果是字典类
element.text 结果是文本
参考:https://www.cnblogs.com/descusr/archive/2012/06/20/2557075.html
Xpath 案例
参考https://blog.csdn.net/naonao77/article/details/88129994
待补充。。。。
--- End ---
DataWhale 组队学习爬虫 Task2相关推荐
- 第8期Datawhale组队学习计划
第8期Datawhale组队学习计划马上就要开始啦 这次共组织15个组队学习,涵盖了AI领域从理论知识到动手实践的内容 按照下面给出的最完备学习路线分类,难度系数分为低.中.高三档,可以按照需要参加 ...
- Datawhale组队学习之MySQL-task2
Datawhale组队学习之MySQL-task2 1. MySQL表数据类型 ---->数据类型定义了列可以存储哪些数据种类. MySQL表中数据类型有: 1.1,数值类型: MySQL中支持 ...
- Datawhale组队学习周报(第047周)
本周报总结了从 2021年01月03日至2022年01月09日,Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. ...
- Datawhale组队学习周报(第041周)
本周报总结了从 11月22日至11月28日,Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. 第 31 期组队学习 ...
- Datawhale组队学习周报(第040周)
本周报总结了从 11月15日至11月21日,Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. 第 31 期组队学习 ...
- Datawhale组队学习周报(第038周)
本周报总结了从 11月01日至11月07日,Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. 第 30 期组队学习 ...
- Datawhale组队学习周报(第035周)
希望开设的开源内容 目前Datawhale的开源内容分为两种:第一种是已经囊括在我们的学习路线图内的Datawhale精品课,第二种是暂未囊括在我们的学习路线图内的Datawhale打磨课.我们根据您 ...
- Datawhale组队学习周报(第032周)
希望开设的开源内容 目前Datawhale的开源内容分为两种:第一种是已经囊括在我们的学习路线图内的Datawhale精品课,第二种是暂未囊括在我们的学习路线图内的Datawhale打磨课.我们根据您 ...
- Datawhale组队学习周报(第021周)
本文总结了本周(07月05日~07月11日)Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. 第 25 期组队学习 ...
最新文章
- iOS定义静态变量、静态常量、全局变量
- RHEL7.0系统相关配置
- 10.16 ln软硬链接的创建等
- 每天一道LeetCode-----将链表每k个节点逆序一次
- JAVA开发环境及其开发
- C#窗体内控件大小随窗体等比例变化
- seo建设者_SEO建设者,有哪些说不出的苦?
- 教程-上传应用公钥并获取支付宝公钥
- 【Python】comtypes模块Windows环境下使用批量转换成PDF文件
- Gitter - 高颜值GitHub小程序客户端诞生记
- Python的贝叶斯网络学习库pgmpy介绍和使用
- Linux下服务器搭建(5)——CentOS下Redis的安装
- Springboot 之 自定义配置文件及读取配置文件
- mysql优化的基本原则和方向
- Team Project 设想 -- 基于用户信息的学术搜索
- [ 4w字 ] JavaSE总结(基础+高级+多线程+面试题)
- 9008刷机工具_黔隆科技刷机教程OPPOR11T忘记密码免刷机保资料解屏幕锁教程
- 联想服务器加装显卡无显示,Lenovo双显卡机型安装显卡驱动方案汇总
- 皮尔斯晶振电路的参数计算
- 1.新建laravel项目
热门文章
- 字符串写入到json文件
- 【Linux】对于make/Makefile的编写
- 解锁网易云音乐小工具_什么?网易云音乐又变灰了
- SUN开源基于TET的CTI和iSCSI测试工具
- AI 作画领域中的“神笔马良”是怎样炼成的?
- 软件设计模式——适配器模式
- 计算机主板diy,DIY电脑配件立即选——主板篇
- 计算机 教授级职称评定,工程技术应用研究员(俗称正高,教授级高工等等)职称评定...
- x86架构手机_为什么苹果放弃的是x86,而不是ARM?
- 机器人URDF文件和xacro文件介绍