任务描述:

2.1 学习beautifulsoup

  1. 学习beautifulsoup,并使用beautifulsoup提取内容。

  2. 使用beautifulsoup提取丁香园论坛的回复内容。

  3. 丁香园直通点:http://www.dxy.cn/bbs/thread/626626#626626 。

  4. 参考资料:https://blog.csdn.net/wwq114/article/details/88085875

2.2学习xpath

  1. 学习xpath,使用lxml+xpath提取内容。

  2. 使用xpath提取丁香园论坛的回复内容。

  3. 丁香园直通点:http://www.dxy.cn/bbs/thread/626626#626626 。

  4. 参考资料: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的div

  • page.xpath(u"/descendant::*[text()]")
    表示任意多层的中间节点(相同的节点)下任意标签之间的内容,也即实现蜘蛛抓取页面内容功能。

  • 不同节点之间的内容获取 (假如需要获取"取不到的内容"这几个字,该怎么做的?)
    xpath(u"//div[tail='<br />']")    # 失败.....:(
    xpath(u"/body/div[tail]")    # 失败.....:(

    <div class="news">1. <b>无流量站点清理公告</b>&nbsp;&nbsp;2013-02-22<br/>取不到的内容
    </div>
    <div class="news"> 2. <strong>无流量站点清理公告</strong>&nbsp;&nbsp;2013-02-22<br />取不到的内容
    </div>
    <div class="news"> 3. <span>无流量站点清理公告</span>&nbsp;&nbsp;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相关推荐

  1. 第8期Datawhale组队学习计划

    第8期Datawhale组队学习计划马上就要开始啦 这次共组织15个组队学习,涵盖了AI领域从理论知识到动手实践的内容 按照下面给出的最完备学习路线分类,难度系数分为低.中.高三档,可以按照需要参加 ...

  2. Datawhale组队学习之MySQL-task2

    Datawhale组队学习之MySQL-task2 1. MySQL表数据类型 ---->数据类型定义了列可以存储哪些数据种类. MySQL表中数据类型有: 1.1,数值类型: MySQL中支持 ...

  3. Datawhale组队学习周报(第047周)

    本周报总结了从 2021年01月03日至2022年01月09日,Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. ...

  4. Datawhale组队学习周报(第041周)

    本周报总结了从 11月22日至11月28日,Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. 第 31 期组队学习 ...

  5. Datawhale组队学习周报(第040周)

    本周报总结了从 11月15日至11月21日,Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. 第 31 期组队学习 ...

  6. Datawhale组队学习周报(第038周)

    本周报总结了从 11月01日至11月07日,Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. 第 30 期组队学习 ...

  7. Datawhale组队学习周报(第035周)

    希望开设的开源内容 目前Datawhale的开源内容分为两种:第一种是已经囊括在我们的学习路线图内的Datawhale精品课,第二种是暂未囊括在我们的学习路线图内的Datawhale打磨课.我们根据您 ...

  8. Datawhale组队学习周报(第032周)

    希望开设的开源内容 目前Datawhale的开源内容分为两种:第一种是已经囊括在我们的学习路线图内的Datawhale精品课,第二种是暂未囊括在我们的学习路线图内的Datawhale打磨课.我们根据您 ...

  9. Datawhale组队学习周报(第021周)

    本文总结了本周(07月05日~07月11日)Datawhale组队学习的运行情况,我们一直秉承"与学习者一起成长的理念",希望这个活动能够让更多的学习者受益. 第 25 期组队学习 ...

最新文章

  1. iOS定义静态变量、静态常量、全局变量
  2. RHEL7.0系统相关配置
  3. 10.16 ln软硬链接的创建等
  4. 每天一道LeetCode-----将链表每k个节点逆序一次
  5. JAVA开发环境及其开发
  6. C#窗体内控件大小随窗体等比例变化
  7. seo建设者_SEO建设者,有哪些说不出的苦?
  8. 教程-上传应用公钥并获取支付宝公钥
  9. 【Python】comtypes模块Windows环境下使用批量转换成PDF文件
  10. Gitter - 高颜值GitHub小程序客户端诞生记
  11. Python的贝叶斯网络学习库pgmpy介绍和使用
  12. Linux下服务器搭建(5)——CentOS下Redis的安装
  13. Springboot 之 自定义配置文件及读取配置文件
  14. mysql优化的基本原则和方向
  15. Team Project 设想 -- 基于用户信息的学术搜索
  16. [ 4w字 ] JavaSE总结(基础+高级+多线程+面试题)
  17. 9008刷机工具_黔隆科技刷机教程OPPOR11T忘记密码免刷机保资料解屏幕锁教程
  18. 联想服务器加装显卡无显示,Lenovo双显卡机型安装显卡驱动方案汇总
  19. 皮尔斯晶振电路的参数计算
  20. 1.新建laravel项目

热门文章

  1. 字符串写入到json文件
  2. 【Linux】对于make/Makefile的编写
  3. 解锁网易云音乐小工具_什么?网易云音乐又变灰了
  4. SUN开源基于TET的CTI和iSCSI测试工具
  5. AI 作画领域中的“神笔马良”是怎样炼成的?
  6. 软件设计模式——适配器模式
  7. 计算机主板diy,DIY电脑配件立即选——主板篇
  8. 计算机 教授级职称评定,工程技术应用研究员(俗称正高,教授级高工等等)职称评定...
  9. x86架构手机_为什么苹果放弃的是x86,而不是ARM?
  10. 机器人URDF文件和xacro文件介绍