python3简单爬虫

允我心安 提交于 2020-04-06 19:51:54

    刚接触爬虫,由于本科主要是学java的,因此之前从java入手爬虫。其实就是模拟http请求,然后将返回的html代码提取自己想要的数据。不过说起来很简单,作为小白,实现起来还是不容易阿。

    之前稍微看了下一个java的框架源代码(还没全部看完,不过和还是会抽时间看看的),不过导师让我用python实现,因而转入python(导师很喜欢python的样子阿)。

    说起python的环境搭建等等,我作为刚入python的小白其实还不清楚,直接下载了一个python3的源码,然后,照着操作安装了下,其实很简单,不多说了。

    爬网页第一步就是要获取html代码

        说来python获取html十分简单,只要几行就可以了,把我给震惊到了!!像java还是要写不少行的,再加上异常,代码看着还是挺臃肿的(不过习惯了)。

#coding=utf-8
import urllib.request

def getHtml(url):
    response= urllib.request.urlopen(url)
    html = response.read()
    return html

html = getHtml("http://www.baidu.com")

print(html)

       这里爬取了百度首页的html代码,没错,这是这么简单。

        这里用了一个urllib.request模块,其实我觉得把java代码封装下,写起来也没几行(纯属小白看法)。

        试过了baidu之后想爬取下大众点评的首页,出现了403 forbid错误,一番查询后发现时缺少User-Agent,因此换一种方式,先创建一个request对象,然后将其加入头部即可:

request=urllib.request.Request(url)
request.add_header("User-Agent","xxx")
response=urllib.request.urlopen(request)
html=response.read()
print(html)

        就是这么简单!

        但还有编码的问题,返回的数据并没有解码,只要html.decode("utf-8")就可以了,具体的编码格式参照该网页的charset

不过也可以用chardet来检测该网页是什么编码,chardet模块需要下载,在命令行输入pip install chardet 即可。

import chardet
charset = chardet.detect(html)
if(charset['encoding'] != None):
    html = html.decode(charset['encoding'])
    return html

         上述代码的html就是之前获取到的html,然后用chardet检测下,获取其中的encoding编码,用这个编码解码即可。

        

          最后这个差点让我崩溃,哎,不得不吐糟,这个问题困扰了我整整一天,研究了很长时间,毕竟小白啊,很多东西还要学。这个问题就是用p3的这个获取html其实是字节而非字符串(这也是上面要用decode解码的原因),但是问题是这个字节可能是压缩过的。

        这个问题是怎么来的呢,是在我爬取http://health.sina.com.cn/disease/department/knx/ 这个页面的时候出现的错误,返回的是这样一串东西b'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03\xd5}iw\x1b\xc7\x95......    然后我还异想天开的用上述方法解码,然后悲剧了UnicodeDecodeError: 'utf-8' codec can't decode byte 0x8b in position 1: invalid start byte,我的天,然后我就一直在研究解码的问题了~~~~~,可是关键不在于解码啊,所以苦苦得不到结果。实在没办法,只能请大师兄帮我一起研究下什么个情况。

        后来我们发现http://health.sina.com.cn/disease/department/kns/,爬取这个有时候能成功,有时候失败,这就很奇怪,这是什么个情况!!!!没办法,用Fiddler工具看下吧(正好之前下了这个抓包工具,很强大!!)然后来了一组同一网站有成功有失败的请求,仔细观察它们到底有啥差别,然后惊讶的发现,失败的那个响应头(应该是响应头里的吧)里多了个 Content-Encoding: gzip,尼玛!!!学linux,正好知道这个gzip,这不是压缩的一个命令么!!!难怪失败的response body应该要有3w多字节,实际只有1w多了。

        既然已经有了方向,自然要看看到底是不是这个Content-Encoding: gzip在作怪了,这时候就要解压缩啊,百度后有了结果,由于这是字节的压缩,因此需要用到BytesIO和gzip,注意py3里BytesIO已经移到了io包里了(又百度半天)

from io import BytesIO
import gzip
#这里省略获取response的代码
if(response.headers.get('Content-Encoding')=='gzip'):
    compresseddata = response.read()
    # gzip解压缩
    compressedstream = BytesIO(compresseddata)
    gzipper = gzip.GzipFile(fileobj=compressedstream)
    html = gzipper.read()
    #解压缩完成
    html = html.decode("UTF-8")#这里才是根据网页charset解码问题
    print(html)

        困扰了一天的问题总算解决了,哎,作为小白也是不容易啊!!还是要感谢下大师兄陪我一起折腾啊!!!希望能帮助到一些人,也以便我未来查阅。

        


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!