第053讲: 论一只爬虫的自我修养 | 学习记录(小甲鱼零基础入门学习Python)

(标答出处: 鱼C论坛)
《零基础入门学习Python》


本节知识点:


什么叫爬虫?

网络爬虫又称为网络蜘蛛(Spider),如果你把整个互联网想象为一个蜘蛛网的构造,每个网站或域名都是一个节点,那我们这只蜘蛛就是在上面爬来爬去,在不同的网页上爬来爬去,顺便获得我们需要的资源,抓取最有用的。做过网站的朋友一定很熟悉,我们之所以能够通过百度、谷歌这样的搜索引擎检索到你的网页,靠的就是他们每天派出大量的蜘蛛在互联网上爬来爬去,对网页中的每个关键字建立索引,然后建立索引数据库,经过了复杂的排序算法之后,这些结果将按照搜索关键词的相关度的高低展现在我们的眼前。我们先从编写一段小爬虫代码开始,然后不断地来改进它。

要使用Python编写爬虫代码,我们要解决的第一个问题是:
Python如何访问互联网?

好在Python为此准备好了电池,Python为此准备的电池叫做:urllib
URL的一般格式为(代方括号的为可选项):
protocol://hostname[:port]/path/[;parameters][?query]#fragment

URL由三部分组成:
- 第一部分是协议:http,https,ftp,file,ed2k...
- 第二部分是存放资源的服务器的域名系统或IP地址(有时候要包含端口号,各种传输协议都有默认的端口号,如http的默认端口为80)
- 第三部分是资源的具体地址,如目录或文件名等。

说完URL,我们现在可以来谈一下 urllib 这个模块了,Python 3 其实对这个模块进行了挺大的改动,以前有urllib和urllib2 两个模块,Python3 干脆把它们合并在了一起并做了统一。其实 urllib 并不是一个模块,而是一个包。我们来查一下文档就知道了(我们说过,有问题,找文档。)

在这里插入图片描述
urllib 其实是一个包,其中包含4个模块,request 、error、parse 和 robotparser,

我们主要讲解 request 这个模块,这个模块也是最复杂的,因为它包含了对服务器的请求和发出、跳转、代理、安全等几大方面。

我们点进去会发现文档非常长,从头看到尾是不可能的,这时候怎么办呢?建议百度、谷歌,查询 urllib.request 的用法,或者查询 Python3 如何访问网页,也可以得到想要的结果。你会得到,使用 urlopen() 这个函数。
在这里插入图片描述
urlopen() 函数除了第一个参数 url 是必需的外,后面的都有默认参数和可选参数,文档告诉我们,url 可以是一个字符串或者 Request object。Request object 是什么,我们下节课讲解。我们猜测 url 为一个字符串是应该就是域名地址的字符串,我们先来尝个鲜:(之所以选择https://ilovefishc.com这个网页,是因为这个网页的源代码量较少,其他的网站会直接把IELD搞崩溃,不信你可以试试 https://www.baidu.com。)

>>> import urllib.request
>>> response = urllib.request.urlopen("https://ilovefishc.com")
>>> html = response.read()
>>> print(html)
b'<!DOCTYPE html>\n<html lang="en">\n<head>\n    <meta charset="UTF-8">\n    <meta name="viewport" content="width=device-width, initial-scale=1.0">\n    <meta name="keywords" content="\xe9\xb1\xbcC\xe5\xb7\xa5\xe4\xbd\x9c\xe5\xae\xa4|\xe5\x85\x8d\xe8\xb4\xb9\xe7\xbc\x96\xe7\xa8\x8b\xe8\xa7\x86\xe9\xa2\x91\xe6\x95\x99\xe5\xad\xa6|Python\xe6\x95\x99\xe5\xad\xa6|Web\xe5\xbc\x80\xe5\x8f\x91\xe6\x95\x99\xe5\xad\xa6|\xe5\x85\xa8\xe6\xa0\x88\xe5\xbc\x80\xe5\x8f\x91\xe6\x95\x99\xe5\xad\xa6|C\xe8\xaf\xad\xe8\xa8\x80\xe6\x95\x99\xe5\xad\xa6|\xe6\xb1\x87\xe7\xbc\x96\xe6\x95\x99\xe5\xad\xa6|Win32\xe5\xbc\x80\xe5\x8f\x91|\xe5\x8a\xa0\xe5\xaf\x86\xe4\xb8\x8e\xe8\xa7\xa3\xe5\xaf\x86|Linux\xe6\x95\x99\xe5\xad\xa6">\n    <meta name="description" content="\xe9\xb1\xbcC\xe5\xb7\xa5\xe4\xbd\x9c\xe5\xae\xa4\xe4\xb8\xba\xe5\xa4\xa7\xe5\xae\xb6\xe6\x8f\x90\xe4\xbe\x9b\xe6\x9c\x80\xe6\x9c\x89\xe8\xb6\xa3\xe7\x9a\x84\xe7\xbc\x96\xe7\xa8\x8b\xe8\xa7\x86\xe9\xa2\x91\xe6\x95\x99\xe5\xad\xa6\xe3\x80\x82">\n    <meta name="author" content="\xe9\xb1\xbcC\xe5\xb7\xa5\xe4\xbd\x9c\xe5\xae\xa4">\n    <title>\xe9\xb1\xbcC\xe5\xb7\xa5\xe4\xbd\x9c\xe5\xae\xa4-\xe5\x85\x8d\xe8\xb4\xb9\xe7\xbc\x96\xe7\xa8\x8b\xe8\xa7\x86\xe9\xa2\x91\xe6\x95\x99\xe5\xad\xa6|Python\xe6\x95\x99\xe5\xad\xa6|Web\xe5\xbc\x80\xe5\x8f\x91\xe6\x95\x99\xe5\xad\xa6|\xe5\x85\xa8\xe6\xa0\x88\xe5\xbc\x80\xe5\x8f\x91\xe6\x95\x99\xe5\xad\xa6|C\xe8\xaf\xad\xe8\xa8\x80\xe6\x95\x99\xe5\xad\xa6|\xe6\xb1\x87\xe7\xbc\x96\xe6\x95\x99\xe5\xad\xa6|Win32\xe5\xbc\x80\xe5\x8f\x91|\xe5\x8a\xa0\xe5\xaf\x86\xe4\xb8\x8e\xe8\xa7\xa3\xe5\xaf\x86|Linux\xe6\x95\x99\xe5\xad\xa6</title>\n    <link rel="shortcut icon" type="image/x-icon" href="img/favicon.ico">\n    <link rel="stylesheet" href="css/styles.css">\n    <script src="js/jq.js"></script>\n    <script src="https://cdn.bootcss.com/timelinejs/2.36.0/js/storyjs-embed.js"></script>\n    <script src="https://cdnjs.cloudflare.com/ajax/libs/timelinejs/2.36.0/js/storyjs-embed.js" defer></script>\n    <!-- <script src="https://fishc.oss-cn-hangzhou.aliyuncs.com/Web/js/embed.js"></script> -->\n    <script>\n        $(document).ready(function() {\n            var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;\n\n            createStoryJS({\n                type:       \'timeline\',\n                width:      \'auto\',\n                height:     windowHeight,\n                source:     \'data.json\',\n                start_at_end:true,                          //OPTIONAL START AT LATEST DATE\n                embed_id:   \'my-timeline\'\n            });\n\n        });\n    </script>\n    <!-- END TimelineJS -->\n</head>\n<body>\n<div id="my-timeline"></div>\n</body>\n</html>\n'

得到的字符串是一个以 b 开头(二进制)字符串。得到的字符串似乎和我们所理解的网页代码不一样,但是我们又看到了很熟悉的身影(例如:div,link rel等),但是在这个网页,如果右键审查元素
在这里插入图片描述
我们会发现网页的代码很整齐,那这是怎么回事呢?为什么Python这里高的一团糟,我们刚才说了,Python这里直接得到的是byte类型(二进制编码),所以我们可以对它进行解码操作,我们先来看一下这个网页的编码方式是:UTF-8。

>>> html = html.decode("utf-8")
>>> print(html)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta name="keywords" content="鱼C工作室|免费编程视频教学|Python教学|Web开发教学|全栈开发教学|C语言教学|汇编教学|Win32开发|加密与解密|Linux教学">
    <meta name="description" content="鱼C工作室为大家提供最有趣的编程视频教学。">
    <meta name="author" content="鱼C工作室">
    <title>鱼C工作室-免费编程视频教学|Python教学|Web开发教学|全栈开发教学|C语言教学|汇编教学|Win32开发|加密与解密|Linux教学</title>
    <link rel="shortcut icon" type="image/x-icon" href="img/favicon.ico">
    <link rel="stylesheet" href="css/styles.css">
    <script src="js/jq.js"></script>
    <script src="https://cdn.bootcss.com/timelinejs/2.36.0/js/storyjs-embed.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/timelinejs/2.36.0/js/storyjs-embed.js" defer></script>
    <!-- <script src="https://fishc.oss-cn-hangzhou.aliyuncs.com/Web/js/embed.js"></script> -->
    <script>
        $(document).ready(function() {
            var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;
 
            createStoryJS({
                type:       'timeline',
                width:      'auto',
                height:     windowHeight,
                source:     'data.json',
                start_at_end:true,                          //OPTIONAL START AT LATEST DATE
                embed_id:   'my-timeline'
            });
 
        });
    </script>
    <!-- END TimelineJS -->
</head>
<body>
<div id="my-timeline"></div>
</body>
</html>

测试题


在这里插入图片描述
答:往后的学习你可能会经常接触 URL 和 URI。URI 是统一资源标识符(Universal Resource Identifier),URL 是统一资源定位符(Universal Resource Locator)。
用一句话概括它们的区别:URI 是用字符串来标识某一互联网资源,而 URL 则是表示资源的地址(我们说某个网站的网址就是 URL),因此 URI 属于父类,而 URL 属于 URI 的子类。
在这里插入图片描述
答:爬虫事实上就是一个程序,用于沿着互联网结点爬行,不断访问不同的网站,以便获取它所需要的资源。
在这里插入图片描述
答:不要重复爬取同一个 URL 的内容。假设你没做这方面的预防,如果一个 URL 的内容中包含该 URL 本身,那么就会陷入无限递归。
在这里插入图片描述
答:在网站的根目录下创建并编辑 robots.txt 文件,用于表明您不希望搜索引擎抓取工具访问您网站上的哪些内容。此文件使用的是 Robots 排除标准,该标准是一项协议,所有正规搜索引擎的蜘蛛均会遵循该协议爬取。既然是协议,那就是需要大家自觉尊重,所以该协议一般对非法爬虫无效。
在这里插入图片描述
答:返回的是一个HTTPResponse的实例对象,它属于http.client模块。

>>> response = urllib.request.urlopen("http://www.fishc.com")
>>> type(response)
<class 'http.client.HTTPResponse'>

调用其read()方法才能读出URL的内容。
在这里插入图片描述
答:HTTPError
在这里插入图片描述
答:UTF-8 编码。一般网页通过点击审查元素,在 标签中的 charset 会显示采用了哪种编码。
在这里插入图片描述
在这里插入图片描述
答:Unicode 编码。扩展阅读关于编码的那篇文章太长了,有鱼油说太生涩难懂,对于对编码问题还一头雾水的鱼油请看 -> 什么是编码?


动动手


在这里插入图片描述

>>> import urllib.request
>>> response = urllib.request.urlopen('http://www.fishc.com')
>>> print(response.read(300))
b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\r\n\t"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r\n\r\n<!-- \r\n(c) 2011 \xc4\xbdubom\xc3\xadr Krupa, CC BY-ND 3.0\r\n -->\t\r\n\r\n<html xmlns="http://www.w3.org/1999/xhtml">\r\n\t<head>\r\n\t\t<meta http-equiv="content-type" content="text/html; charset=utf-8" />\r\n\t\t'

在这里插入图片描述
提示:提供个“电池”给你用 -> 一次性解决你所有的编码检测问题

import urllib.request as ur
import chardet as c

list1 = input("请输入URL:")
response = ur.urlopen(list1).read()
charset = c.detect(response)
values = list(charset.values())
print ('该网页使用的编码是:' + values[0])

运行结果:
在这里插入图片描述
在这里插入图片描述
写的时候因为考虑到如果不转换编码写的话会导致写入的内容过于杂乱,所以将其解码后写入。

import urllib.request as ur
import chardet as c
def main() :
    file1 = open ('urls.txt','r')
    filename = []
    linenum = 0
    weburl = []
    for line in file1 :
        linenum += 1
        filename.append('url_' + str(linenum) +'.txt')
        weburl.append(line)
    file1.close()
    for i in range (linenum) :
        response = ur.urlopen(weburl[i]).read()
        charset = c.detect(response)
        values = list(charset.values())
        response = response.decode(values[0])
        with open (filename[i], 'w',encoding=values[0]) as fw :
            fw.write(response)
    print ('写入完成!')
    
if __name__ == "__main__":
    main()

运行结果:
在这里插入图片描述
在这里插入图片描述
小甲鱼的代码:

import urllib.request
import chardet
 
def main():
    i = 0
    
    with open("urls.txt", "r") as f:
        # 读取待访问的网址
        # 由于urls.txt每一行一个URL
        # 所以按换行符'\n'分割
        urls = f.read().splitlines()
        
    for each_url in urls:
        response = urllib.request.urlopen(each_url)
        html = response.read()
 
        # 识别网页编码
        encode = chardet.detect(html)['encoding']
        if encode == 'GB2312':
            encode = 'GBK'
        
        i += 1
        filename = "url_%d.txt" % i
 
        with open(filename, "w", encoding=encode) as each_file:
            each_file.write(html.decode(encode, "ignore"))
 
if __name__ == "__main__":
    main()

猜你喜欢

转载自blog.csdn.net/qq_38970783/article/details/88427345
今日推荐