【Python】爬虫01_静态网页请求与网页解析

以下是本人基于上课所学的的内容浓缩而成的一篇代码。
主要介绍了get网页请求,BeautifulSoup网页解析,Xpath网页解析。
正则表达式网页解析在下一篇文章中解释。

2021/12/8首发于csdn,有错误和不足欢迎指出。
----更新记录----
2021/12/11将正则表达式部分移入下一篇文章,修正了最后一行代码缩进,增加了对BeautifulSoup的.string方法的解释。

'''
http协议使用了请求/响应模型,爬虫作为客户端模拟发起请求,服务器做出响应
连接web服务器,爬虫发送http请求,服务器接收请求并返回htttp响应,释放TCP连接,爬虫解析HTML内容
正是因为连接会被关闭,所以需要使用cookie(以键值对形式保存)对用户历史操作(如表单密码的提交)进行记录
'''
import requests  # requests请求库
import chardet  # 字符串/文件编码检测模块
from bs4 import BeautifulSoup  # bs4解析网页
from lxml import etree  # Xpath解析网页

# 基本参数
url = "http://www.tipdm.com/"
# 请求头header = user-agent
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
                         AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36 Edg/96.0.1054.41"}
timeout1 = 2  # 设置超时时间为2s,超时后会报错,程序自动停止
timeout2 = 0.001  # 超时时间过短会直接报错

'''get请求'''
# 发送请求用encoding
rqg = requests.get(url, headers=headers, timeout=timeout1)
print("结果类型:", type(rqg))  # 查看结果类型
print("状态码:", rqg.status_code)  # 查看状态码
# 当requests库解析编码错误时,用chardet库指定编码
print("编码:", rqg.encoding)  # 查看编码
print("detect方法检测结果:", chardet.detect(rqg.content))  # 头部里面有个charset=utf-8
rqg.encoding = chardet.detect(rqg.content)['encoding']  # 将检测到的编码赋值给rqg.encoding
print("改变后的编码:", rqg.encoding)  # 查看改变后的编码
print("响应头:", rqg.headers)  # 查看响应头
# print("网页内容:", rqg.text)  # 查看网页内容


# 初始化html,先获取html再做解析
# 获取网页用decode
html = rqg.content.decode("utf-8")  # 内容上与rqg.text一致

'''BeautifulSoup解析网页'''
# 生成BeautifulSoup对象,使用"lxml"解析器或用"html.parser"解析器
# 这个对象内并没有真正的html/xml的tag,但是可以当做tag使用
soup = BeautifulSoup(html, "lxml")  # BeautifulSoup对象
# soup = BeautifulSoup(open("index.html", encoding = "utf-8"), "html.parser")  # 解析本地网页
# print("输出格式化的BeautifulSoup对象:", soup.prettify())  # 只保存了关键的标记与内容,而且去除了注释(comment对象)
tag = soup.ul  # 找到html中第一个ul标签块里包含的内容,找所有ul用find_all
# print("查看第一个u标签块l包含的内容", tag)
print("tag第一个标签的名字(其实已经知道是ul了):", tag.name)
print("tag第一个标签的属性及取值:", tag.attrs)  # 属性是键值对显示,tag.attrs["id"]可以只看id的值,引号不可以去掉
print("tag里第一个li标签块的内容:", tag.li)
# print("tag里所有文字部分的内容:", tag.text)
# print("使用get_text()获取所有文字的文本内容:", tag.get_text())
print("tag里第一个li的文字内容:", tag.li.text)

# NavigableString对象即包含在标签块内的文字
# 可以用.string(这样会获得NavigableString对象,且被注释的文本会被显示,但不知道它原来是注释)
# .text/.get_text方式获取(这样获得的是str)
# NavigableString对象无法被编辑,但可以用replace_with方法替换
print("tag里第一个li的文字内容:", tag.li.string)
print("tag.text,tag.li.get_text()和tag.string对象类型:", type(tag.li.text), type(tag.li.get_text()), type(tag.li.string))

# find_all与find方法
print("查找第一个ul块:", soup.find("ul"))
print("查找所有的class='menu'的ul块,结果为一个列表,如果找不到就为空列表。\
      注意写法是class_,不是class,id还是原来那样写:", soup.find_all("ul", class_='menu'))
# Find_all得到是列表,可以切片方式得到元素
s1 = soup.find_all('ul')
print("切片结果:", s1[0:2])  # 结果是前两个ul标签块里面的内容
# 存储获取的文本与链接
# urls = []
# text = []
# for tag in soup.ul.find_all("a"):
#     urls.append(tag.get("herf"))
#     text.append(tag.get_text())
for t in soup.ul.find_all("a"):
    print(t.get_text(), t.get("herf"), end="\n")


'''Xpath解析网页'''
# 生成Xpath对象,parser是解析器
# Xpth可以自动修正html文本,例如自动闭合未闭合的标签
xp = etree.HTML(html, parser=etree.HTMLParser(encoding='utf-8'))
# tostring方法可以输出修正后的html代码,也可以直接读取文本进行解析,但结果为bytes类型,需要decode转str输出
# result = etree.tostring(html, encoding='utf-8', pretty_print=True, method="html")
# print(result.decode('utf-8'))

# Xpath用类似正则的方式来匹配HTML中的内容
print("所有的a标记,不管在什么位置", xp.xpath("//a"))

print("body/div里的第一个a结点", xp.xpath("body/div/a[1]"))
print("body/div里的最后一个a结点", xp.xpath("body/div/a[last()]"))
print("body/div里的倒数第二个a结点", xp.xpath("body/div/a[last()-1]"))
print("body/div里的前两个a结点", xp.xpath("body/div/a[position()<3]"))
# print("body里所有div里的xx元素值大于10的结点", xp.xpath("body/div[xx>10.00]))
print("body里所有class属性值为container clearfix的div结点", xp.xpath("body/div[@class='container clearfix']"))

print("body里所有div下所有的内容:", xp.xpath("body/div/*"))
print("body里所有带有属性的前两个div结点", xp.xpath("body/div[@* and position()<3]"))
print("body里所有id值以co开头的div结点", xp.xpath("body/div[starts-with(@id,'co')"))
# contanins已经是无效谓词了
# print("body里所有id值含co和en的div结点", xp.xpath("body/div[contanins(@id,'co')]"))

print("head里所有的title的文本内容:", xp.xpath("head/title/text()"))
r2 = xp.xpath("//p[starts-with(@class,'p1')]") #查找所有以“p1”开始的class属性的p
for j in r2:  # 查看该结点下所有的文本
    t2 = j.xpath('string(.)')
	print(t2)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值