访问网页、爬取html页面
要想爬取网页第一步就要访问网页。
由于机器访问网页会加大服务器的负荷,所以一般服务器会通过user-agent的http头部信息、robots.txt排除网络爬虫协议、访问频率、提交表单、验证码的手段来限制非人类的访问。
前三者还可以解决轻松应对,但是对于提交表单和验证码暂时只能通过cookie来维持登录状态来进行爬取,没有更好地手段来应对这方面限制。
Request库
凡是使用第三方库,我们首先要安装好python 包管理工具(pip),安装方法详见pip官网,安装好后就可以在cmd或者anaconda prompt使用pip命令安装其它python第三方库了。
requests库给出了7种向服务器提交请求的方法各自对应着http请求方法
requests.request() | 构造一个请求,支撑以下各方法的基础方法 |
requests.get() | 获取html网页的主要方法,对应于http的GET |
requests.head() | 获取html网页头信息的方法,对应于http的HEAD,response对象使用headers内置方法返回头部信息。 |
还有post、put、patch、delete方法由于我们一般较少使用且从**kwargs可变参数来看,每个方法需要的参数都差不多的只是http请求方法不同,在这里就不进行详细介绍了,在此重点介绍经常使用的get方法
requests.get(url,params=None,**kwargs)
-
url 拟获取页面的url链接
-
params 向url添加额外参数,要求输入字典或者字节流格式
-
**kwargs:12个控制访问的参数,其中介绍七个常用的参数。
timeout:规定允许请求超时的时间,以秒为单位,超过规定时间则抛出TimeoutError异常;
headers:定制request的头部信息,躲避封杀;
cookies:添加cookies状态信息,避免再次提交表单
data:输入字典、字节序列或文件对象,作为Request的内容
json:输入JSON格式数据,作为Request的内容
files:以字典形式来传输文件
proxies:以字典形式设定代理服务器或ip地址(例如:{ “http”: “http://10.10.1.10:3128”, “https”: “http://10.10.1.10:1080”, } )
查看源代码可以发现,严格意义上来说requests库其实只有request这一个方法。
通过requests.get()便获得了requests库的Response对象,下面详细介绍一下Response对象的内置方法
r.raise_for_status() | 在方法内部判断r.status_code是否等于200,最好搭配try、except异常处理使用 |
r.status_code | 返回http请求的状态码 |
r.text | 返回响应页面内容的字符串形式 |
r.encoding | 规定了Response对象的内容编码方式或者从http header的charset猜测响应内容的编码方式 |
r.apparent_encoding | 从内容中分析出响应内容编码方式,虽然分析的编码更加准确,但比较消耗资源耗时更长 |
r.content | 返回响应页面内容的二进制形式 |
常用代码框架
import requests as req try: r = req.get('http://www.bing.com/',/ headers='Mozilla/5.0 ') r.raise_for_status()# 检测访问网页是否正常 r.encoding = r.apparent_encoding # 防止返回网页内容乱码,但一般通过查看源代码来确定网页编码方式 return r.text# 以字符串形式返回响应的页面内容 except: return ''
urllib库
相较于requests库,urllib操作较为复杂,但现在urllib2已经与urllib3合并为urllib库并分为urllib.request、urllib.error、urllib.parse、urllib.robotparser四个模块功能较为齐全。
小编主要用requests和beautifulsoup而urllib用得少,所以在这里就只能介绍简单urllib的用法了。
req = urllib.request.Request(url) # 修改http请求的头部信息 req.add_header('User-Agent','Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.96 Mobile Safari/537.36' response = urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None) #将http.client.HTTPResponse object对象返回其字符串形式并解码。 html = response.read().decode('utf-8') #关闭操作,避免过于频繁地访问服务器 response.close()
这个是urllib里最常用的代码块了,url指定访问链接,如果有需要还可以命名data形参,向服务器提交数据。
代理
#参数是一个字典{'类型':'代理ip:端口号'} proxy_support = urllib.request.ProxyHandler({}) # 定制、创建一个opener opener = urllib.request.build_opener(opener) #安装opener urllib.request.install_opener(opener) #用代理访问网页 response = urllib.request.urlopen(url)
解析网页、提取数据
BeautifulSoup也叫beautifulsoup4或bs4,是用来从服务器返回的网页内容(html、xml文件)中提取数据的第三方库。一般用简称bs4引入beautifulsoup4库。
Beautiful Soup库提供的解析器
Python标准库 | BeautifulSoup(markup, “html.parser”) | python的内置标准库、执行速度适中、文档容错能力强 | Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差 |
lxml html解析器 | BeautifulSoup(markup,‘lxml’) | 速度快、文档容错能力强 | 需要安装C语言库 |
lxml xml解析器 | BeautifulSoup(markup, [“lxml”, “xml”])、BeautifulSoup(markup, “xml”) | 速度快、唯一支持xml的解析器 | 需要安装C语言库 |
html5lib | BeautifulSoup(markup, “html5lib”) | 最好的容错性、以浏览器的方式解析文档、生成html5格式的文档 | 速度慢、不依赖外部扩展 |
一般使用html.parser解析器居多
BeautifulSoup类的内置方法
soup = BeautifulSoup(html,'html.parser')
soup.tag | 返回一对指定标签的开头结尾 |
soup.tag.name | 返回标签名,soup.tag.parent.name可返回父级标签名,可以逐级向上返回 |
soup.tag.attrs | 以字典的形式返回指定标签的所有属性,但它不是字典而是bs4.element.Tag |
soup.tag.string | 返回标签内的非属性字符串也可以返回注释,但它不是字符类型而是bs4.element.NavigableString |
soup.tag.prettify | 为html文本<>及其内容增加\n,增加可读性 |
遍历标签树之下行遍历
soup.contents | 下行遍历,返回子节点的列表,将标签所有子级节点存入列表,如果有类似p标签那样的层级标签,也会把换行符\n存入列表 |
soup.children | 下行遍历,返回子节点的迭代类型,与contents类似,用于循环遍历子级节点 |
soup.descendants | 下行遍历,返回子孙节点的迭代类型,包含所有子孙节点,用于循环遍历 |
soup.parent | 上行遍历,返回节点的父级标签 |
soup.parents | 上行遍历,返回节点的父级标签的迭代类型,用于循环遍历先辈节点,包括soup本身 |
soup.next_sibling | 平行遍历,按照html文本顺序返回下一个平行节点标签 |
soup.previous_sibling | 平行遍历,按照html文本顺序返回上一个平行节点标签 |
soup.next_siblings | 按照html文本顺序,返回后续所有平行节点迭代类型 |
soup.previous_siblings | 按照html文本顺序,返回前续所有平行节点迭代类型 |
只有同属于上一级标签内的同级标签,才能平行遍历
内容查找
在内容查找方面,我们还可以继续使用bs4的方法
# 返回一个列表类型,存储查找的结果 soup.find_all(name,attrs,recursive,string,**kwargs)
- name:对标签名称的检索字符串,可以查找多个标签名
- attrs:对标签属性值的检索字符串,可标注属性检索,标注‘class’属性写‘class_’,避免被认为是定义类
- recursive:是否对子孙全部检索,默认为True
- string:对<>……</>中字符串区域的检索字符串
同样的方法还有find(),它返回的也是bs4的实例对象还可以再用find_all()来进一步查找信息且多用于仅有一个独特标签的检索
re
Re库是python的标准库,主要用于字符串匹配和正则表达式使用,采取贪婪匹配。如果你需要的信息存在于键值对当中,使用re库最适合不过了。
Re库主要功能函数
regex = re.compile() | 将符合正则表达式语法的字符串转换为真正的正则表达式, regex.search(string)==re.search(pattern,string)以此内推以下所有函数的用法 |
re.search(pattern,string,flags=0) | 在一个字符串中搜索匹配正则表达式的第一个位置,返回match对象 |
re.match(pattern,string,flags=0) | 从一个字符串的开始位置起匹配正则表达式,返回match对象 |
re.findall(pattern,string,flags=0) | 搜索字符串,以列表类型返回全部能匹配的子串 |
re.split(pattern,string,maxsplit=0,flags=0) | 将一个字符串按照正则表达式匹配结果进行分割,返回列表类型 |
re.finditer(pattern,string,flags=0) | 搜索字符串,返回一个匹配结果的迭代类型,每个迭代元素是match对象 |
re.sub(pattern,repl,string,count=0,flags=0) | 在一个字符串中替代所有匹配正则表达式的子串,返回替换后的字符串 |
pattern表示正则表达式的字符串或原生字符串、string待匹配字符串、flags正则表达式使用时的控制标记、repl表示替换匹配字符串的字符串。match对象用group方法返回匹配结果
数据整理
经过一番“大海捞针”过后,还要考虑如何工整舒适地输出结果了。
str.format()字符串类型的格式化函数就是个很好用的工具了。
如果出现排版乱的问题,调整宽度再使用chr(12288)空格填充
输入图片
with open(filename,'wb') as file: file.write(img)
要注意的是输入非文本数据一定要以二进制方式写入或追加到文件中,img也一定是二进制数据流。
如果是储存文本文件,记得加上\n,\t分隔字符串。
scrapy爬虫框架
scrapy是个能够帮助用户实现专业网络爬虫的爬虫框架,不同于小编之前介绍的requests、Beautifulsoup、re这些函数功能库,可实现网站级爬虫,但对于处理js、提交表单、应对验证码等功能还有望扩展。
END
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试