python爬虫-自学1

参考:python网络数据采集.pdf

 

思考爬虫的想法:

1.通过网站域名获取HTML数据

2.根据目标信息解析数据

3.存储目标信息

4.更换网页重复抓取

以后加深学习应该也就是从这4个点深入了 


1.通过网站域名获取HTML数据

首先向网络服务器发送GET请求以获得具体网页,在从网页读取HTML内容,然后就是信息提取,把我们需要的的内容提取出来

这里首先要用到 urllib 库

获取HTML实现代码:

from urllib.request import urlopen

html = urlopen("http://www.panxiaonan.cc")
print(html.read())

把他保存为.py结尾的文件,然后在终端运行

这会输出这个网页的全部HTML代码

python爬虫1.png

 

代码解释:

from urllib.request import urlopen

查找Python的urllib库里的request模块,导入其中的函数urlopen

urllib是python的标准库,不用另外安装,包含了 从网络请求数据,处理cookie,还有处理请求头和用户代理的函数

它还可以读取网页上的图像文件或者其他网上的文件流

这个库的Python官方文档 https://docs.python.org/3/library/urllib.html


2.根据目标信息解析数据

下载HTML后就要解析它,这里我们就要用上 BeautifulSoup库,这个库需要另外安装

加入BeautifulSoup库后,代码如下:


from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("http://www.pythonscraping.com/pages/page1.html")
bsObj = BeautifulSoup(html.read())
print(bsObj.h1)
我的python是3.7.7版本的 运行出错


Warning (from warnings module):
  File "E:\python\study\new.py", line 5
    bsObj = BeautifulSoup(html.read())
GuessedAtParserWarning: No parser was explicitly specified, so I'm using the best available HTML parser for this system ("lxml"). This usually isn't a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently.

The code that caused this warning is on line 5 of the file E:\python\study\new.py. To get rid of this warning, pass the additional argument 'features="lxml"' to the BeautifulSoup constructor.


<h1>An Interesting Title<</h1>

虽然输出了结果,但是报了个错误

百度翻译:

guessedattparserwarning:没有显式指定解析器,所以我使用了这个系统中最好的HTML解析器(“lxml”)。这通常不是问题,但如果您在另一个系统上或在不同的虚拟环境中运行此代码,它可能会使用不同的解析器并表现出不同的行为。


引起此警告的代码位于文件E:\\python\\study的第5行\\新建.py. 要消除此警告,请将附加参数“features=”lxml“”传递给beauthulsoup构造函数。

应该是是这本书之后BeautifulSoup 更新了 要加一个 HTML解析器的参数,更改之后:


from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("http://www.pythonscraping.com/pages/page1.html")
bsObj = BeautifulSoup(html.read(), "lxml")
print(bsObj.h1)
 现在就正常输出了 没有报错



代码解释:

bsObj = BeautifulSoup(html.read(), "lxml")

把HTML代码传入BeautifulSoup对象,将其转换成如下格式:

python爬虫2.jpg

这里跳过了body 直接获取了h1,所以我们调用标签可以不用考虑 标签的层级

也可以这样调用:

bsObj.html.body.h1

bsObj.body.h1

bsObj.html.h1

不过一个网页中一般有许多相同的标签如: li img div 等等,这个只能获取HTML代码中的第一个标签


获取HTML时可能出现的错误和异常处理

可能出现的错误就两个:

1.网页不存在(404或者其他?)

2.服务器不存在

第一种错误 urlopen函数会抛出 HTTPError 异常  使用:


try:
 html = urlopen("http://www.pythonscraping.com/pages/page1.html")
except HTTPError as e:
 print(e)
 # 返回空值,中断程序,或者执行另一个方案
else:
 # 程序继续。注意:如果你已经在上面异常捕捉那一段代码里返回或中断(break),
 # 那么就不需要使用else语句了,这段代码也不会执行
 第二种错误 urlopen函数会返回一个 None 对象

处理的话就加一个if 判断一下就好了吧 代码:


if html is None:
 print("URL is not found")
else:
 # 程序继续
 另外在使用 BeautifulSoup 也可能出现错误 就是你以为存在的标签实际不存在

bsObj = BeautifulSoup(html.read(), "lxml")

这是就会返回一个 None 对象 这是再调用这个 None 对象的子标签就会报错 返回一个AttributeError错误

如下所示:

print(bsObj.nonExistentTag.someTag)

这时就会返回一个异常:

AttributeError: 'NoneType' object has no attribute 'someTag'

处理方法和上面 HTTPError 异常 类似:


try:
    badContent = bsObj.nonExistingTag.anotherTag
except AttributeError as e:
    print("Tag was not found")
else:
    if badContent == None:
        print ("Tag was not found")
    else:
        print(badContent)
 这样我们把之前的几个异常处理合在一起就是这样了:


from urllib.request import urlopen
from urllib.error import HTTPError, URLError
from bs4 import BeautifulSoup

def getTitle(url):
    try:
        html = urlopen(url)
    except (HTTPError, URLError) as e:
        return None
    try:
        bsObj = BeautifulSoup(html.read(), "lxml")
        title = bsObj.body.h1
    except AttributeError as e:
        return None
    return title

title = getTitle("http://www.pythonscraping.com/pages/page1.html")
if title == None:
    print("没找到")
else:
    print(title)
 代码解释:

这里我们定义了一个 getTitle 函数 来获取网页标题 把所有可能出错的代码都封装在这个函数里 统一处理

这样出错就就会返回None对象

本文标签: python爬虫 urllib BeautifulSoup
转载声明:本文为网中小南的原创文章,转载请注明原文地址,谢谢合作

发表评论: