Python3 网络爬虫 Web Crawler 之 urlopen, BeautifulSoup, regex 和 lambda

前言

这一篇仍有问题未解决 剩余:2

写爬虫时刻注意try-except

有问题就去查文档 When in doubt, read the docs!

常见错误类型
  • from urllib.error import HTTPError ,页面找不到了
  • from urllib.error import URLError 服务器不存在

HTTPErrorURLError 的子类,所以先except HTTPError

基本格式

from urllib.request import urlopen
from urllib.request import HTTPError
from urllib.request import URLError

try:
    html = urlopen("https://baidu.com")
except HTTPError as e:
    print(e)
    # return null break
except URLError as e:
    print(e)
else:
    print('work well')
# else 语句在try成功时使用
  • BeautifulSouptagNone 的情况

bs.nonExistTag.tag 会报错Attribute Error,需要排查tag为None的情况

bs = BeautifulSoup(html, 'html.parser')

try:
    badContent = bs.tag.othertag
except AttributeError as e:
    print("Tag not found!")
else:
    if badContent = None:
        print('Subtag not found')
    else:
        print('work well')
        
def getTitle(url):
    try:
        html = urlopen(url)
    except HTTPError as e:
        print(e)
        return None
    try:
        bs = BeautifulSoup(html, 'html.parser')
        title = bs.body.h1
    except AttributeError as e:
        print(e)
        return None
    return title
BeautifulSoup基本语法
  • find_all

find_all -> findAll (别称),可以搜索所有满足条件的标签,并形成 ResultSet ,近似理解为列表,与 find 不同——形成单个标签。
​​​​​​find_all 和 find 的区别
find_all 有limit参数,确定搜索个数

find_all(tag, attributes, recursive, text, limit, keywords)
find(tag, attributes, recursive, text, keywords)
nameList = bs.findAll('div', {'class': 'home'})
for name in nameList:
    print(name.get_text())
    # print(name.text())
bs.find_all(['h1', 'h2', 'h3'], {'class': ['home', 'outside']})
# class_=['home', 'outside']
# 括号里的都满足
# recursive——布尔值,代表是否递归搜索,默认为TRUE,能够搜到子孙节点

可以发现bs.find_all(id='text')bs.find_all('', {'id': 'text'}) 等效

疑问:我不理解上式中,为何加空字符串。并且实践后返回空

text搜索
nameList = bs.find_all(text='the prince')
# 返回由text内容构成的列表,这里是 ['the prince', 'the prince']
子孙节点和兄弟节点
  • 所有的子节点都是子孙节点,所有子孙节点不一定是子节点

子节点的调用需要find()而不是find_all(),因为二者返回值不一样

for item in bs.find(...).children:
    pass	# 生成迭代对象,使用for循环
  • .next_siblings.previous_siblings 也只适用于find,生成迭代对象(不包括自身
  • .next_sibling.previous_sibling 只是tag类型的上下两个tag类型是个函数

bs.find(...).next_siblingsbs.find(...).next_sibling

正则表达式的补充

?! “Does not contain”,不是很常用,仅限于了解

|,运算优先级最小,匹配两边各一个,但是可以这样用apple|banana|carrot,匹配三个substring

正则表达式与BeautiSoup结合

记得先import re

bs.find_all('img', {'src': re.compile(r'\.\./img/img\d?\.jpg)})

标签属性 Attribute

Tag.attrs 返回字典,keys 为属性名称

Tag.attrs['src'] or Tag['src'],使用时确保keys存在,否则报错 AttributeError

疑问Tag.attrs.get['class'] or Tag.get['class'] 为什么使用无效?是关键字的问题吗

lambda表达式——接收标签,返回boolean
bs.findAll(lambda tag: tag.get_text() == 'I'm fine)

违法行为 bs.findAll(tag, lambda tag: tag.get('src') == 'listen')

因为tag对象在lambda中接收

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值