零基础学习爬虫并实战

总第63篇

本篇主要从爬虫是什么、爬虫的一般流程、爬虫各个流程的实现方法、爬虫实例四个方面分享零基础了解爬虫,并进行简单的实战。

在阅读下面之前,我们需要对网页有个基本的了解,知道什么是标签,什么是属性,以及知道标题是放在哪,内容是放在哪,这些关于网站的基础知识。

可查看我前几篇关于网页基础知识的推文:

网页是怎么构成的?

网页的修饰

网页的行为

01|爬虫是什么:

爬虫又叫网页数据抓取,就是通过向浏览器发出请求并得到回应,把回应的内容抓取保存到本地的过程叫做爬虫。

比如,我要获取猫眼电影的TOP100榜电影的信息,其中包括电影名、主演、上映时间、评分以及封面图片。我们可以选择手动一条条登记,也可以写一个爬虫(通过浏览器向猫眼电影发出一个request然后得到一个response)去获取这些信息。

02|爬虫一般流程:

1、发起请求,通过HTTP库向目标站点发起请求,即发送一个Request。一般会包括下面这些部分。

2、获取响应内容,如果服务器能够正常响应,会得到一个Response,Response的内容便是要获取的页面内容,类型可能有HTML,Json字符串,二进制数据(图片视频等一般为二进制数据)等类型。

3、解析内容,得到的内容如果是HTML,可以用正则表达式和网页解析库进行解析;如果是Json,直接转为Json对象解析;如果是二进制数据,可以保存也可以做进一步处理。

json.dumps():对json数据进行编码。(Python编码为json类型) json.loads():对json数据进行解码。(json解码为Python类型)

4、保存数据,保存形式有多种,可以存为文本,也可以保存至数据库,或者保存到特定格式的文件。

03|实现上述爬虫过程的具体方法:

1、获取内容

这里的获取内容包括前面提到的request和response两个过程。

Urllib库

直接将目标网站链接url传递给urlopen函数即可。

import urllib.request
response = urllib.request.urlopen('http://www.baidu.com')
print(response)#打印出得到回应的一行代码
print(response.read())#打印出获得的html内容
print(response.read().decode("utf-8"))#以“utf-8”编码的格式打印出获得的html内容

关于decode和encode的一些科普

字符串在Python内部的表示是unicode编码,因此,在做编码转换时,通常需要以unicode作为中间编码,即先将其他编码的字符串解码(decode)成unicode,再从unicode编码(encode)成另一种编码。 decode的作用是将其他编码的字符串转换成unicode编码,如str1.decode(‘gb2312’),表示将gb2312编码的字符串str1转换成unicode编码。 encode的作用是将unicode编码转换成其他编码的字符串,如str2.encode(‘gb2312’),表示将unicode编码的字符串str2转换成gb2312编码。 因此,转码的时候一定要先搞明白,字符串str是什么编码,然后decode成unicode,然后再encode成其他编码。

request库

将目标网站链接url传递给request.get函数即可。

import requests
response = requests.get('http://httpbin.org/get')
response = requests.get("http://httpbin.org/get?name=germey&age=22")#带有参数的url
print(response.text)#获取response的具体html内容

2、解析内容

所谓的解析内容就是用一定的方法从获得的全部内容中取出我们想要的某一部分内容,开头讲述的猫眼电影top100的获取,我们通过第一步获取内容取得是整个网页的所有部分,但我们只需要这所有部分中的标题、主演、评分等信息。

正则表达式

正则表达式是用一些符号去表示要匹配的内容,然后将其放在过程1中获得的全部内容中区匹配我们想要的内容。

模式

描述

\w

匹配字母数字及下划线

\W

匹配非字母数字下划线

\s

匹配任意空白字符,等价于 [\t\n\r\f].

\S

匹配任意非空字符

\d

匹配任意数字,等价于 [0-9]

\D

匹配任意非数字

\A

匹配字符串开始

\Z

匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串

\z

匹配字符串结束

\G

匹配最后匹配完成的位置

\n

匹配一个换行符

\t

匹配一个制表符

^

匹配字符串的开头

$

匹配字符串的末尾。

.

匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。

[…]

用来表示一组字符,单独列出:[amk] 匹配 ‘a’,’m’或’k’

[^…]

不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。

*

匹配0个或多个的表达式。

+

匹配1个或多个的表达式。

?

匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式

{n}

精确匹配n个前面表达式。

{n, m}

匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式

a|b

匹配a或b

( )

匹配括号内的表达式,也表示一个组

上面的表是直接copy的崔庆才老师的表,老师在天善智能有开设爬虫入门课程,课程链接:https://edu.hellobi.com/course/157/lessons

在正则表达式中我们常用的是re.findall(pattern,html,re.S),三个参数依次表示目标匹配内容(正则表达式书写的)、待匹配的全部内容(过程1获得的全部内容)、匹配模式。在后面的实例中我们就是用的正则表达式进行解析的,具体内容看后面的实例。

BeautifualSoup

BeautifulSoup是python自带的一个库,在这个库中我们常用下面这个选择器:

find_all( name , attrs , recursive , text , **kwargs )

参数依次要查找的标签名、属性和内容。该选择器输出内容为所有符合条件的项。

from bs4 import BeautifulSoup
soup = BeautifulSoup(html, 'lxml')#html表示要待解析的内容,lxml表示解析方式print(soup.find_all('ul'))#表示输出所有标签名为“ul”的内容
print(type(soup.find_all('ul')[0]))##表示输出第一个标签名为“ul”的内容
print(soup.find_all(attrs={'id': 'list-1'}))#表示输出属性id=list对应的值
print(soup.find_all(text='Jay'))#获取标签内的内容为“Jay”的项

3、保存内容到本地

先使用open创建并打开一个file对象,然后使用write方法将内容写入到这个file对象中。

with open('result.txt', 'a', encoding='utf-8') as f:#open用于打开一个文件,并创建一个file对象
        f.write(json.dumps(content, ensure_ascii=False) + '\n')#write()方法的参数为字符串形式,所以需要用json_dumps将字典形式转化为字符串
        f.close()

04|爬取猫眼电影实例:

获取内容

import requests
response = requests.get("http://maoyan.com/board/4")
print (response.text)

解析内容

import re#导入re库pattern = re.compile('<dd>.*?board-index.*?>(\d+)</i>.*?data-src="(.*?)".*?name"><a.*?>(.*?)</a>.*?star">(.*?)</p>.*?releasetime">(.*?)</p>.*?integer">(.*?)</i>.*?fraction">(.*?)</i>.*?</dd>', re.S)
items = re.findall(pattern, response.text)

(部分解析结果)

保存到本地

import jsonwith open('result.txt', 'a', encoding='utf-8') as f:#open用于打开一个文件,并创建一个file对象
        f.write(json.dumps(items, ensure_ascii=False) + '\n')#write()方法的参数为字符串形式,所以需要用json_dumps将字典形式转化为字符串
        f.close()

这样一个包含有电影信息的名为result.txt文件就保存到本地了。整个爬虫过程就完成了。

原文发布于微信公众号 - 张俊红(zhangjunhong0428)

原文发表时间:2017-04-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏轮子工厂

5. 很“迷”的字符与字符串

最近一直在为自己的浏览量而担忧啦,都快被厂长大人约谈了……我真的有尽力在写稿子哦,所以也请各位老铁,如果觉得我的文章还不错就转发到朋友圈或者微信群之类的,让更多...

13220
来自专栏V站

PHP反序列化深入理解

在PHP中右serialize()和unserialize()两个函数,php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。u...

24350
来自专栏转载gongluck的CSDN博客

c++ 中__declspec 的用法

c++ 中__declspec 的用法 语法说明: __declspec ( extended-decl-modifier-seq ) 扩展修饰符: ...

1.1K70
来自专栏微信公众号:Java团长

Java堆和栈的区别

在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配。当在一段代码块中定义一个变量时,Java就在栈中为这个变量分配内存空间,当超过变量的作...

27630
来自专栏小古哥的博客园

JavaScript闭包的深入理解

闭包算是javascript中一个比较难理解的概念,想要深入理解闭包的原理,首先需要搞清楚其他几个概念: 一、栈内存和堆内存 学过C/C++的同学可能知道,计算...

40470
来自专栏北京马哥教育

提升Python程序性能的7个习惯

使用局部变量替换模块名字空间中的变量,例如 ls = os.linesep。一方面可以提高程序性能,局部变量查找速度更快;另一方面可用简短标识符替代冗长的模块变...

9500
来自专栏python小白到大牛

零基础学习python编程不可错过的学习总结,小白福利!

通过以上可以看到我们写的很贱的程序随便保存了一个.txt结尾的格式,竟然也执行了,并没有按照统一要求的.py格式来设计, 那是不是说明后缀名可以说是任意的呢?理...

16730
来自专栏noteless

[五] JavaIO之InputStream OutputStream简介 方法列表说明

16420
来自专栏Brian

Python进阶教程(二)

概述 在上一篇博客中,我们介绍了Python进阶教程(一),还有一些新的技巧没有翻译完,我们下面来继续我们的翻译。 Intermediate Python 中译...

50180
来自专栏Jackson0714

C#多线程之旅(4)——APM初探

417130

扫码关注云+社区

领取腾讯云代金券