@TOC基于python的网络爬虫学习笔记1
网络爬虫主要包含两个任务:1.下载目标网页;2.从目标网页提取需要的数据。
网络爬虫的主要类型:1.通用网络爬虫;2.聚焦网络爬虫;3.增量式网络爬虫;4.深层页面爬虫。
简易网络爬虫架构:1.URL管理器;2.网页下载器;3.网页解析器;4.输出管理器。
网络爬虫常用工具:python
常用的主要有两个库:
1)Urllib库。Urllib库是python内置的HTTP请求库,可以直接使用。
2)Requests库。Requests库是用python语言编写的。它比更加方便,使用它可以节约我们大量的工作,完全满足HTTP的测试需求。简单易用。
网页解析器,即主要用于从HTML网页信息中提取需要的、有价值的的数据和链接。python中主要有三种工具:
1)正则表达式。描述一种字符串匹配的模式,提取效率高但表达式不直观,写起来比较复杂。
2)Lxml库。使用的是XPath语法,可在XML文档中对元素和属性进行遍历。直观易懂,配合Chrome或Firefox浏览器写起来简单、运行效率高。
3)Beautiful Soup。Beautiful Soup可以从HTML或XML文件中提取数据的python库。简单易学,但比前两种解析速度慢。
帮助实现爬虫项目的半成品。结合具体应用场景调用框架的接口,通过少量的代码实现一个爬虫项目。python中常见的有三种:
1)Scrapy框架。Scrapy框架是python中最著名、最受欢迎的爬虫框架,相对成熟。它是为了爬取网站数据、提取结构性数据而编写,也可以用于数据挖掘、信息处理或是存储历史数据等一系列程序中。
2)Pyspider框架。Pyspider框架是国人编写的、用python实现的。可在浏览器界面上进行脚本的编写、功能的调度和爬取结果的实时查看,后端利用常用数据库进行爬取结果的存储,还能定时设置任务以及任务优先级等。
3)Cola框架。Cola框架是一个分布式的爬虫框架,用户只需编写几个特定的函数,而不需关注分布式运行的细节,任务会自动分配到多台机器上,整个过程对于用户是透明的。
从客户端到服务器端的请求消息。HTTP请求由请求方法、请求头部、请求正文3部分组成。
1)请求方法:
GET方法:请求指定页面信息,并返回实体主体。
POST方法:向指定资源提交数据进行处理请求,数据被包含在请求体中。
平时打开一个网站一般使用的是GET方法,如果涉及向网站提交数据(如登陆),就用POST方法。除此之外,还有一些其他的请求方法,如:HEAD 、PUT、 DELETE 、CONNECT 、OPTIONS 、TRACE等,实际爬虫中较少用到。
2)请求头部:
请求头部包含很多有关客户端环境和请求正文的有用信息。一般网站服务器最常用的反爬虫措施就是通过读取请求头部的用户代理(user-agent)信息,判断该请求是来自正常的浏览器还是爬虫。
打开某浏览器—空白处右键—检查—network—刷新页面----。。。。
3)Request库请求方法:
在这里插入代码片
import requests
#获取豆瓣首页。得到响应对象
response = requests.get('https://www.douban.com/')
#获取文本方式的响应体内容
text_r = response.text
#查看响应体编码方式
encode_type = response.encoding
#设置响应体编码方式
response.encoding = 'utf-8'
#查看网页源码
org_code = response.content
#响应状态码,常见状态码及含义:200---请求成功;301---资源被永久转移到其它URL;
#404---请求的资源或网页不存在;500---内部服务器错误。
status = response.status_code
#定制请求头部,字典dict形式
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’
}
#查看设置的请求头部
head = response.request.headers
#或者
head = response.headers
#重定向
response.history
#超时设置,表示若在timeout=3秒内收不到豆瓣服务器的响应,就会抛出timeout异常。
response = requests.get('https://www.douban.com/',timeout = 3)
#查看实际请求的URL
response.url
#传递url参数:
payload = {'q' : 'python' , 'cat' : '1001'}
r = requests.get('https://www.douban.com/search', params = payload)
r.url
#https://www.douban.com/search?q=python&cat=1001
Lxml大部分功能存在于etree下,下面主要使用etree这个模块实现网页解析。
#加载所需包
import requests
from lxml import etree
#定义一个HTML源码作为示例,如下所示:
html="""
- first item
- second item
- third item
- fourth item
- fifth item
- else item
another item
"""
1)通过路径查找元素
XPath语法实际上就是使用这种层级的路径来找到相应元素的,类似与人们常使用的地址,从大的犯罪一直缩小到具体的某个地址上。但如果要找的某个元素或地址是独一无二的,可以直接指明这个地址,不需要层级关系来一层一层的定位。
#利用HTML源码初始化etree
selector = etree.HTML(html)
#查找所有的标签,XPath用//表示从根节点开始查找
all_li = selector.xpath('//div/ul/li')
#因为源码中标签是唯一的因此也可以从根节点取定位ul开始查找
all_li = selector.xpath('//ul/li')
#定位某一个- 标签,eg:第一个(**XPath中的序号是从1开始的,这与python切片的初始编号不同)
li_1 = selector.xpath('//ul/li[1]')
#现在提取第一个
- 标签下的标签里面的文本“first item”
li_1_text = selector.xpath('//ul/li[1]/a/text()') # [“first item”]
#li_1_text 是列表形式输出,若要输出元素则如下:
li_1_text_a = selector.xpath('//ul/li[1]/a/text()')[0] # “first item”
2)通过属性查找元素
在htm中有< li class=“item-0”>、< a href=“link1.html” >这样的代码,这里的class 和href 分别是标签< li >和< a >的属性。因此,也可通过属性来定位元素。
#查找第三个
li_3 = selector.xpath('//ul/li[@class="item-inactive"]')
#因为class="item-inactive" 在源码中是唯一的,因此,也可如下:(*表示任意字符)
li_3 = selector.xpath('//*[@class="item-inactive"]')
#接下来提取a 标签里面的文本
li_3_text = selector.xpath('//*[@class="item-inactive"]/a/text()')
#上述既可以在单引号里面使用双引号,也可以在双引号里面使用单引号,但不可同时使用单引号或者双引号。
#li_3_text也可等价于如下:
li_3_a_text = selector.xpath('//*[@href="link3.html"]/text()')
#提取li_3中href的属性值,而不是标签a的文本值,如下:
li_3_a_label = selector.xpath('//ul/li[3]/a/@href')
#取出所有li标签的class属性
all_li_class = selector.xpath('//li/@class')
3)XPath的其他用法
部分匹配:starts-with; 相对路径 ; string()提取代码段所有文本
#提取前5个li 标签
li_before_5 = selector.xpath('//li[starts-with(@class,"item-")]')
#提取第三个li标签下a标签的文本,相对路径,接着li标签继续向下查找
li_3_text = li_before_5.xpath('a[3]/text()')
#提取ul这一层本层的文本
ul_text = selector.xpath('//ul/text()')
#提取ul 里面各层级的所有文本
all_text = selector.xpath('string(//ul)')
#使用列表推导式取出所有的文本
[s.strip() for s in all_text.strip().split('\n')]