Python爬虫学习

我从小语文就没及格希望大家不要见笑,我使用的是Python3.7。我发现如果单纯学习Python太容易枯燥了,我就结合爬虫一起学习了。

使用urllib

在Python3.x中urllib库是Python内置的HTTP请求库,也就是说不用额外安装即可使用。包含下面四个模块。

  • 1、 request:它是最基本的HTTP请求模块,用来模拟发送请求。类似于在浏览器中直接输入网址,然后回车一样。
  • 2、 error:异常处理模块,如果出现请求错误,我们可以捕获这些错误,进行重试或者其他操作保证程序不会意外停止。
  • 3、 parse:一个工具模块,提供许多URl的处理方法,如拆分、解析、合并等。
  • 4、 robotparser:顾名思义主要用于识别网站的robot.txt文件,判断哪些可以爬,哪些不可以爬,这个用的比较少。 urlopen()
    我们来试验下:
    1
    2
    3
    4
    5
    #encoding:UTF-8
    import urllib.request

    response = urllib.request.urlopen('http://www.lanbainan.cn')
    print(response.read().decode('UTF-8'))

1.png
这里调用read()能得到返回内容。
注:请注意不要整体复制代码否则会报错。
这里的输出效果和在浏览器中查看审查元素是一样的。既然我们得到了源代码,链接、图片地址、文本信息就都可以提取出来了。至于怎么提取等下写!( ̄▽ ̄)~*
data参数
如果使用该参数,并且如果它是字节流编码格式的内容,即bytes类型,需要通过bytes()转化,一旦传递了这个参数,请求方式就由GET变为POST。

1
2
3
4
5
6
import urllib.request
import urllib.parse

data = bytes(urllib.parse.urlencode({'word':'hello'}),encoding='utf8')
response = urllib.request.urlopen('http://httpbin.org/post',data=data)
print(response.read())

word是参数,hello是值
2.png
这是模拟表单提交的方式,以POST方式传递数据。
Request
我们知道了利用urlopen()方法可以实现最基本的请求发起,但是这几个简单的参数不足以构建一个完整的请求。如果在请求中加入headers等信息,就需要request类来构建。
Request通过怎样的参数来构造,如下:
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

  • 第一个参数url用于请求URL。
  • 第二个参数data如果要传,必须传bytes (字节流)类型的。如果它是字典,可以先用 urllib.parse模块里的urlencode()编码。
  • 第三个参数headers是一个字典,它就是请求头,我们可以在构造请求时通过headers参数直接构造,也可以通过调用请求实例的add header()方法添加。添加请求头最常用的用法就是通过修改User-Agent来伪装浏览器,默认的User-Agent是 Python-urllib,我们可以通过修改它来伪装浏览器。比如要伪装火狐浏览器,可以把它设置为:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0
  • 第四个参数origin_req_host指的是请求方的host名称或者IP地址。
  • 第五个参数unverifiable表示这个请求是否是无法验证的,默认是False,意思就是说用户没有足够权限来选择接收这个请求的结果。例如,我们请求一个HTML文档中的图片,但是我们没有自动抓取图像的权限,这时unverifiable的值就是True.
  • 第六个参数method是一个字符串,用来指示请求使用的方法,比如GET, POST和PUT等。

这里我们使用多个参数来构建请求:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from urllib import request,parse

url = 'http://httpbin.org/post'
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0',
'Host':'httpbin.org'
}
dict = {
'name':'hello'
}
data = bytes(parse.urlencode(dict),encoding='utf8')
req = request.Request(url=url,data=data,headers=headers,method='POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))

3.png
在这里我们使用了4个参数来构建一个请求,url就是要请求的URL,headers中指定了User-Agent和host,data用urlencode()和bytes()方法转为字节流,method还指定了请求方式为POST。
注:httpbin.org这个站点它可以提供HTTP请求测试

正确安装requests库
直接命令行安装,Windows、linux、mac都可以
pip3 install request
在requests库得到中请求方法

1
2
3
4
5
r = requests.post('http://httpbin.org/post')
r = requests.put('http://httpbin.org/put')
r = requests.delete('http://httpbin.org/delete')
r = requests.head('http://httpbin.org/get')
r = requests.options('http://httpbin.org/get')

再把代码简化下:

1
2
3
4
5
6
7
#encoding:UTF-8
import requests

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0'}
r = requests.get('https://baike.baidu.com/item/%E6%A2%A6%E6%A2%A6%C2%B7%E8%B4%9D%E8%8E%89%E9%9B%85%C2%B7%E6%88%B4%E6%AF%94%E8%B7%AF%E5%85%8B', headers = headers)
r.encoding='utf-8'
print(r.text)

4.png
在使用requests库时,r.text返回的是Unicode型数据,会中文乱码。通过r.encoding属性来改变它,大多数 unicode 字符集都能被无缝地解码。
安装lxml、beautifulsoup4
在Windows、Linux命令行下pip3 install lxml,在Windows下安装错误,就用wheel安装,下载对应系统和python版本的lxml,本地安装pip3 install lxml‑4.2.3‑cp37‑cp37m‑win_amd64.whl
注:cp对应的是Python版本,3.7就是cp37。
Beautiful soup是一个第三方模块,命令行下pip3 install beautifulsoup4,Beautiful Soup可以很方便地帮我们提取出 HTML 或 XML标签中的内容,准备工作完成。

1
2
3
4
5
6
7
8
#encoding:UTF-8
import requests

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0'}
r = requests.get('https://baike.baidu.com/item/%E6%A2%A6%E6%A2%A6%C2%B7%E8%B4%9D%E8%8E%89%E9%9B%85%C2%B7%E6%88%B4%E6%AF%94%E8%B7%AF%E5%85%8B', headers = headers)
r.encoding='utf-8'
content=r.text
print(content)

我们将r.text的内容存储在content变量中(不知道这个说法对不对),打印content。先熟悉基本BeautifulSoup用法
代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
content = """
<html><head><title>梦梦·贝莉雅·戴比路克</title></head>
<body>
梦梦好可爱(*╹▽╹*)
</body>
</html>
"""
from bs4 import BeautifulSoup
soup = BeautifulSoup(content,'lxml')
#创建bs对象,bs是使用的python默认的解析器,lxml也是解析器
print(soup.title)
#这里打印的是title

5.png
切入正题,我们将从百度百科将梦梦的介绍爬下来。她的名字在h1标签中
6.png

1
bb = soup.h1.get_text()  #get_text()能去除标签

剩下的内容都在<div class="para" label-module="para">中。

1
dd = soup.find_all(class_='para')

这个时候代码应该是:

#encoding:UTF-8
from bs4 import BeautifulSoup
import requests

headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0'}
r = requests.get('https://baike.baidu.com/item/%E6%A2%A6%E6%A2%A6%C2%B7%E8%B4%9D%E8%8E%89%E9%9B%85%C2%B7%E6%88%B4%E6%AF%94%E8%B7%AF%E5%85%8B', headers = headers)
r.encoding='utf-8'
content=r.text
soup = BeautifulSoup(r.text,'lxml')

dd = soup.find_all(class_='para')
bb = soup.h1.get_text()
print(bb)
print('---------------------')
for aa in dd:
    print(aa.get_text())

7.png
这里print('---------------------')只是为了分割标题与正文。
恭喜我终于入门了。美滋滋啊!

我碰上的坑

我写py文件的时候,一直出现IndentationError:expected an indented block,我对自己的错误深信不疑,改了又改,查了资料才知道Python语言是一款对缩进非常敏感的语言,空格和Tab不能混用,然后我就不缩进了,不缩进也错了,大佬说:“冒号下一行多半要缩进,该缩就缩”。
string和get_text()这两个功能虽说差不多,但是还是有差别sting是数据类型,get_text是方法。前者提取百度百科会出现None,后者不会。
8.png

到此结束

如有错误请联系lanbaidetanlang@qq.com
4b90f603738da977d3f5a635b851f8198718e3d2.jpg.gif

文章目录
  1. 1. 使用urllib
  2. 2. 我碰上的坑
  3. 3. 到此结束