爬虫实践
一、数据提取
- 非结构化数据处理
- 文本、电话号码、邮箱地址>>>正则表达式
- html文件>>>正则表达式、xpath语法、css选择器
- 结构化数据处理
- Json>>>json path、将json转化成python类型
- xml文件>>>转化成python类型、css选择器、xpath、正则表达式
正则表达式学习成本高,用于爬虫的次数没有xpath情况用的多,正则处理html文档很累,我们可以使用xpath
思路: html>>>xml文档
使用xpath语法查找html节点或者元素
二、使用python提取本地html文件中的内容
思路:获取HTML文件中的内容 读取这个HTML文件, 然后获得这个文件的所有内容,再进行提取。
读取文件 open()
from lxml import html
with open("index1.html", 'r', encoding='UTF-8') as f:
html_data = f.read()
print(html_data)
从html_data中提取 欢迎来到王者荣耀这个标题
# XML 可扩展标记语言
# Xpath XML path language 用于提取文档中的元素
# 使用lxml库来实现Xpath语法的提取
# 安装 lxml
# pip install lxml
# 导入
selector = html.fromstring(html_data)
# 获取h1标题中的内容
# /代表的是根节点
# 要想获取标签中的内容,我们需要在最后面加上/text()
h1 = selector.xpath('/html/body/h1/text()')[0]
print(h1)
获取p标签中的内容
p = selector.xpath('/html/body/p/text()')
print(p)
以上使用的Xpath语法用起来比较麻烦,类似于绝对路径
我们常常使用下面的语法格式:
1. 获取文本(也就是获取标签中的内容,标签对中间夹的部分)
# <a href="http://www.baidu.com">点击跳转至百度</a>
# //代表从任意位置出发 []内的属性是对前面标签的约束,目的是保证唯一性
# //标签1[@属性1="属性值1"]/标签2[@属性1="属性值1"]/.../text()
示例:
# 获取a标签中的内容
a = selector.xpath('//div[@id="container"]/a[1]/text()')[0]
print(a)
# 点击跳转至新浪
sina = selector.xpath('//div[@id="container"]/a[2]/text()')[0]
print(sina)
# 获取鲁班七号这个内容
lu = selector.xpath('//ul[@id="deti"]/li[1]/a/text()')
print(lu[0])
2. 获取属性值
# //标签1[@属性1="属性值1"]/.../@属性名
示例:
# 获取百度链接
link = selector.xpath('//div[@id="container"]/a[1]/@href')
print(link[0])
# 获取鲁班英雄详情链接
link_lu = selector.xpath('//ul[@id="deti"]/li[1]//a/@href')
print(link_lu[0])
# 获取ul所有英雄
ul_list = selector.xpath('//ul[@id="deti"]/li')
print(ul_list)
print(len(ul_list))
# 遍历
for li in ul_list:
hero = li.xpath('text()')
print(hero)
三、访问服务器端的前端代码
使用的是requests库
安装requests
pip install requests
requests 使用文档 https://requests.kennethreitz.org//zh_CN/latest/user/quickstart.html
由于网站的编码方式可能不同,抓取数据之前要先统一编码方式:
# 导入
import requests
url = 'http://www.baidu.com'
# 获取响应
response = requests.get(url)
print(response) # <Response [200]> 200代表响应成功的状态码
print('编码方式为', response.encoding) # 编码方式为 ISO-8859-1
print('响应状态码', response.status_code) # 响应状态码 200
print('获取响应头', response.headers) # 获取响应头 {'Cache-Control': 'private, no-cache, no-store,
# proxy-revalidate, no-transform', 'Connection': 'Keep-Alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html',
# 'Date': 'Fri, 25 Oct 2019 10:58:57 GMT', 'Last-Modified': 'Mon, 23 Jan 2017 13:27:32 GMT', 'Pragma': 'no-cache',
# 'Server': 'bfe/1.0.8.18', 'Set-Cookie': 'BDORZ=27315; max-age=86400; domain=.baidu.com; path=/',
# 'Transfer-Encoding': 'chunked'}
# 修改编码方式
response.encoding = 'utf-8'
data = response.text
print(data)
写入本地 'w' ,write 写入
with open('baidu.html', 'w',encoding='UTF-8') as f:
f.write(data)
data_content = response.content
print(data_content)
response.content和 response.text 的区别
response.text
返回类型:str
解码类型 根据http头部对响应的编码做出有根据的推测,推测文本编码
修改编码方式:response.encoding = 'utf-8'
response.content
返回类型:bytes
解码类型 没有指定
修改编码方式:response.content.decode('utf-8')
添加headers
为什么添加headers?
模拟浏览器访问,欺骗服务器,获取与浏览器一致的内容
headers 的形式:字典
# 没有添加headers参数的知乎网站返回的值是 400
url = 'http://www.zhihu.com'
# res = requests.get(url)
# print(res.status_code) # 400
# 添加header的知乎
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'}
# User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36
response = requests.get(url, headers=headers)
print(response.status_code) # 200 200代表成功了
四、爬虫案例:爬取当当网图书信息
import requests
from lxml import html
def spider(isbn):
""":param #param是参数
当当网图书信息爬虫
"""
# url = "http://search.dangdang.com/?key=python%B4%D3%C8%EB%C3%C5%B5%BD%CA%B5%BC%F9&act=input"
# isbn 国际标准书号(唯一的) 9787115428028
url = "http://search.dangdang.com/?key={}&act=input".format(isbn)
print(url)
# 获取网页的源代码
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'}
html_data = requests.get(url, headers=headers).text
print(html_data)
#使用xpath语法提取我们想要的内容
selector = html.fromstring(html_data)
ul_list = selector.xpath('//div[@id="search_nature_rg"]/ul/li')
print('有{}家商铺售卖此书'.format(len(ul_list)))
# 遍历
for li in ul_list:
# 爬取所有书籍的标题
title = li.xpath('a/@title')[0]
print(title)
# 获取所有购买链接
link = li.xpath('a/@href')[0]
print(link)
# 获取价格
price = li.xpath('p[@class="price"]/span[@class="search_now_price"]/text()')[0]
# print(price)
# 去掉¥符号
price = price.replace('¥', ' ')
print(price)
# 爬取除了当当自营以外的所有店铺,存入容器,以价格进行排序(作业)
isbn = input('请输入您要查询的书号')
spider(isbn)
网友评论