1、常用爬虫库
urllib和requests
2、读取网页
1、首先我们介绍一下urllib的组成模块和安装方法
直接用pip install urllib下载安装此包。
包含的模块和功能:
- urllib.request: 打开和读取url
- urllib.error:处理常见的错误,超时、网址错误等,使用try捕捉
- urllib.parse:解析url
- urllib.robotparse:解析robots.txt文件
2、urlopen使用
urlopen在urllib.request.urlopen()里,源码定义为:
主要传入参数有你要爬取网页的url,设置的超时timeout,data为你可能需要传输的数据(可不传入)。注意timeout是一定要设置的,不然一个网页可能一辈子都不给反馈,陷入僵局呀~~。一般视情况而定,timeout=10代表10秒,是我比较喜欢设置的值。
这个函数返回的是结构体呀,如果你要读取具体内容,需要用read方法,举个例子,爬取百度网页:
'''
请求网页并返回内容
'''
from urllib import request
url = "http://www.baidu.com"
response = request.urlopen(url=url)
print(response.read())
这样就可以了吗,我们会发现打印出的结果是bytes类型,不利于我们观看或者后续操作。故我们需要解码,代码如下:
'''
请求网页并返回内容
'''
from urllib import request
url = "http://www.baidu.com"
response = request.urlopen(url=url)
html = response.read() # 读取返回结果,是bytes,不利于我们使用
print(html)
print(type(html)) # 是bytes
html = html.decode() # 解码
print(html)
3、自动检测网页编码类型
需要第三方包,直接用pip install chardet即可。
为什么需要知道网页编码类型呢,我们不能直接用上面程序中html.decode()进行解码吗?原因就是并不是所有网页都是“utf-8”编码,decode()默认为utf-8,如果我们不对网页编码进行获取直接调用decode的话可能会导致解码后的结果出现乱码。故而我们需要用chardet进行网页编码类型判断,知道网页编码类型后再解码,确保万无一失!
我们来看看具体使用:
'''
自动检测页面编码
'''
from urllib import request
import chardet
url = url = "http://www.baidu.com"
response = request.urlopen(url=url)
html = response.read()
encodingType = chardet.detect(html) # 检测网页编码类型
print(encodingType)
可见,通过chardet检测出的类型为"utf-8",且有0.99的置信度,即基本上没有错误。这样,一个完整的爬去网页+解码的模板程序如下:
'''
读取网页并自动解码
'''
from urllib import request
import chardet
def getHtml(url):
response = request.urlopen(url=url)
html = response.read()
encodingType = chardet.detect(html) # 检测网页编码类型
# encodingType是字典类型,用get方法取出“encoding”的值,如果没有则默认为"utf-8"
html = html.decode(encodingType.get('encoding', 'utf-8'))
return html
if __name__ == '__main__':
url = "http://www.baidu.com"
html = getHtml(url)
print(html)
4、urlopen返回对象
不知道小伙伴们发现没有,之前返回地response是一个结构体,要读取html还需要加一句html = response.read()才能读取网页。接下来我们就仔细地来看看response里面到底都有哪些东西。
'''
看看urlopen返回的信息
'''
from urllib import request
url = 'http://www.baidu.com'
response = request.urlopen(url=url)
print("URL:", response.geturl()) # 返回对象地url
# 请求返回对象的详细信息,比如日期,Cookie,Server等等
print("INFO:\n", response.info())
# 返回响应的状态(200:成功!!!;404:没找到)
print("State Code:", response.getcode())
4、处理error
用urllib.error模块来处理错误,比如断网、服务器链接失败、IP被封等等。用try-except来捕捉异常。
'''
错误模块的使用
'''
from urllib import error, request
url = "http://www.baiiiiiidu.com" # 错误的百度网址
try:
response = request.urlopen(url=url)
html = response.read().decode()
print(html)
except error.HTTPError as e:
print("HTTPError:{}".format(e.reason))
except error.URLError as e: # url错误
print("URLError:{}".format(e.reason))
except error.ContentTooShortError as e:
print("ContentTooShortError{}".format(e.reason))
except Exception as e: # 其他错误
print(e)
这就打印出错误信息啦——
5、向服务器发送数据
举个例子,当我们打开百度一下的时候,往里面输入关键词后能得到返回的内容。这时候,我们可以发现输入的关键词经过编码后加在url里面了。
我们将要输入的内容打包成字典格式,通过parse.urlencode()进行编码即可组成与输入内容相关的url,这里记为fullurl。代码如下:
'''
向服务器发送数据
'''
from urllib import request, parse
url = 'http://baidu.com/s?'
wd = input("请输入关键词:")
# 需要使用字典结构
qs = {"wd": wd}
# 转化url编码
qs = parse.urlencode(qs)
fullurl = url+qs
print("编码之后的url:{}".format(fullurl))
response = request.urlopen(url=fullurl)
html = response.read().decode()
print(html)
6、经典案例:用爬虫打造你的翻译器
各位看官老爷们,这一节的内容就讲完啦~接下来,让我们尝试爬去百度翻译,打造自己的翻译器。
首先,打开百度翻译页面,鼠标右键点击"检查",点击"network",如下图:
接下来,我们尝试往输入框输入单词,例如"girl",会发现红色框里面出现了很多信息。点击黄色框里面的sug,可以看到绿色框里面出现了我们请求的详细信息,如下图:
在绿色框里面是headers信息,具体如下截图:
整个headers信息最主要的是:requestURL,content-type,还有最下面的kw:girl,这是我们向服务器传过去的信息。网页返回的信息呢?点击Respose,里面是一个json格式的返回数据,还需要解码啦~
这样,我们就得到了我们的基本信息,如下:
url | https://fanyi.baidu.com/sug |
---|---|
Content-Type | application/json |
kw | girl |
要传入的信息打包在data里面,注意是字典类型。注意返回的数据是json格式的,需要用json库来解码。 json使用点击此链接。别怕,很简单的。
程序如下:
'''
百度翻译
'''
from urllib import request, parse
import json
url = 'https://fanyi.baidu.com/sug'
data = {'kw': 'girl'}
data = parse.urlencode(data).encode("utf-8")
response = request.urlopen(url, data)
result = json.load(response)
print(result)
可见结果为一个大字典。接下来我们打包程序做一个通用的翻译接口,各位看官拿来就可以用。程序如下:
'''
百度翻译
'''
from urllib import request, parse
import json
def translation(content):
url = 'https://fanyi.baidu.com/sug'
data = {'kw': content}
data = parse.urlencode(data).encode("utf-8")
response = request.urlopen(url, data)
result = json.load(response)
return result['data'][0]
if __name__ == '__main__':
res = translation("我爱你一生一世")
print(res)
3、身份伪装
1、修改headers进行身份伪装
有很多网站都有反爬虫机制,比如通过检查你的header信息,或者是封掉你的ip,这时候我们用urlopen就不够啦。需要用到urllib.request.Request()来模拟浏览器访问,这样就能一定程度上解决反爬机制带来的影响啦。
首先,我们来看看Request类都有哪些需要传入的参数:
需要传入url,data,还有headers等。我们只需要通过修改headers即可完成身份伪装。常见的可以修改“User-Agent”来伪装自己是浏览器。程序如下:
'''
添加身份伪装headers
'''
from urllib import request, parse
import json
url = 'https://fanyi.baidu.com/sug'
data = {'kw': 'girl'}
data = parse.urlencode(data).encode("utf-8")
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko)"
" Chrome/71.0.3578.98 Safari/537.36",
"Content-Length": len(data)
}
req = request.Request(url=url, data=data, headers=headers)
response = request.urlopen(req)
result = json.load(response)
print(result)
有了身份伪装,这下我们加入异常处理和设置超时,写一个更加完成的获取网页的函数,如下:
'''
爬取网页模块: 包含身份伪装、处理异常和设置超时
'''
from urllib import request
import chardet
def getHtml(url):
try:
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko)"
" Chrome/71.0.3578.98 Safari/537.36"
}
req = request.Request(url=url, headers=headers)
response = request.urlopen(req, timeout=10)
html = response.read()
encodingType = chardet.detect(html) # 检测网页编码类型
# encodingType是字典类型,用get方法取出“encoding”的值,如果没有则默认为"utf-8"
html = html.decode(encodingType.get('encoding', 'utf-8'))
return html
except Exception as e:
print(e)
if __name__ == '__main__':
url = "http://www.baidu.com"
html = getHtml(url)
print(html)
2、使用代理IP
代理IP的获取网址 http://www.xicidaili.com
使用步骤——四部曲:
- 设置代理地址
- 创建ProxyHandler
- 创建opener
- 安装opener
程序如下:
'''
代理ip的使用
'''
from urllib import request
url = "http://www.baidu.com"
# 四部曲
proxy = {"http": '120.194.18.90:81'}
proxy_handler = request.ProxyHandler(proxy)
opener = request.build_opener(proxy_handler)
request.install_opener(opener)
try:
response = request.urlopen(url=url, timeout=10)
html = response.read().decode()
print(html)
except Exception as e: # 其他错误
print(e)