导图社区 爬虫基础思维导图
这是一篇关于爬虫基础的思维导图。包括网页基础、HTTP基本原理、web数据爬取、模拟登录等内容、详细的爬虫基础,可以点开查看更详细的信息。
编辑于2021-08-17 09:16:39爬虫基础
概念:网络爬虫(又被称为网页蜘蛛),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。
网页基础
HTML(页面结构)
双标签
head <!--不涉及网页显示的内容,是对网页的设置说明 -->
p <!--p 段落内容-->
div <!--div 网页分区布局功能,不同区域展示不同的内容-->
a <!--a 超链接标签-->
ol <!--ol: order list,有序列表-->
ul <!--ul: un order list,无序列表-->
dl+dt+dd <!--dl+dt+dd: 自定义列表-->
单标签
hr <!--hr horizon 插入水平线,-->
br <!--换行用法-->
img <!--图片标签-->
form标签 <!--form 表单,接收用户提供的数据-->
p, li { white-space: pre-wrap; } <form action="text1"> <!--action地址为点击提交后信息传送的地址--> 姓名:<input type="text"> <br> <!--设置用户输入的内容格式--> 密码:<input type="password"> <br> 性别: <input type="radio" value="男" name="性别" checked="checked"> 男 <!--设置选择按钮供用户选择,value值为用户选项代表的真实值; name为选项分组,同一组选项只允许选择一个;checked表示默认选择的选项;最后边尖括号后边的文字为选择按钮前边显示的内容。--> <input type="radio" value="女" name="性别"> 女 <br> 状态:<input type="radio" value="是"><input type="radio" value="否"> <br> <!--尖括号后没有添加说明,选项上不显示名称--> 下拉选择: <!--select 为下拉选择的内容--> <select> <option>选项一</option> <option>选项二</option> <option>选项三</option> </select> <!----> <input type="submit" value="点击按钮提交信息"> <!--信息提交按钮,点击此按钮后,对信息进行提交(提交的信息,input中一定要指定name属性, 仅对有name属性的input进行提交)--> <br> <input type="button" value="点击按钮更改图片" onclick="change()"></form>
其他标签
注释 <!--注释内容-->
特殊字符
CSS(页面样式)
p, li { white-space: pre-wrap; } <style type="text/css"> /*<!--全局设置字体颜色-->*/ p { color: blue } /*CSS类定义样式,后边可以引用*/ .字体样式 { color: burlywood; font-size: 20px; }</style>
JS(动态交互)
p, li { white-space: pre-wrap; } <script type="text/javascript"> function change() { //document 当前HTML这个文档 document.getElementById("img1").src="毕业.JPG"; }</script>
http基本原理
交互主体
浏览器request
服务器response
地址、协议
url :Uniform Resource Locator,统一资源定位符
http :HyperText Transfer Protocol,即超文本传输协议
https: HyperText Transfer Protocol over Secure Socket Layer,即安全套接字层超文本传输协议
请求方法
get
要数据,请求获取服务器资源
可通过url传递数据给服务器
一般用于查询
post
送数据,向服务器发送数据
通过request body传递数据
一般用于保存数据
put
delete
内容信息
Body
Header
Accept: 浏览器端可以接受的媒体类型
Accept-Encoding: 浏览器接受的编码方式
gb2312
gbk :gb2312的扩展
utf-8
Accept-Language: 浏览器所接受的语言种类
Connection: 表示是否需要持久连接
Cookie: 网站在用户本地的存储少量数据的容器
Host: 被请求资源的网络主机地址和端口号
User-Agent: 客户端操作系统、浏览器名称和版本、CPU版本等
Response响应
Response Status Code
200(一切正常)
404(资源没找到)
500(服务器出错了)
Response Header
Response Body
HTML页面
数据
Robots协议
/robots.txt的文件
User-Agent
Allow
Disallow
web数据爬取
Requests库
安装:pip install requests
get请求:requests.get(url = '***', params = {'key'='value',***} )
post请求:requests.post(url = '***’, data = {'key'='value',***} )
编码问题:res.encoding = ‘***’#给response设置文字编码方式
User-Agent问题:无User-Agent时,可能被禁止访问
p, li { white-space: pre-wrap; } import requests# get请求:1.请求地址与请求参数之间合并并使用?分割;2.分开表示地址和参数# 1.请求地址:https://www.qidian.com/search# 2.请求参数:kw=三国 其中?为分隔符res = requests.get("https://www.qidian.com/search?kw=三国")res1 = requests.get("https://www.qidian.com/search", params={"kw": '三国'})# 返回请求状态代码,200:请求成功print(res.status_code)# 输出返回网页的html代码;如果乱码是因为网页HTML编码问题;在网页的头文件找到编码;res.encoding = "UTF-8" # 指定编码print(res.text)# 如果不能成功访问可能与user agent有关,需要编写头部文件。使用头文件还可以进行浏览器伪装。headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36 Edg/87.0.664.75'} # 头文件采用字典的方式进行表示res_zhihu = requests.get("https://www.zhihu.com", headers=headers) # 带着头文件进行访问res.encoding = "UTF-8" # 指定编码print(res_zhihu.text)
Ajax
通过requests库获取到html代码后,找不到相关的音乐排行信息
原因:Ajax异步加载。使用request是库时需要找到异步加载的url在进行数据爬取
requests-html库
特点:在requests库基础上进一步封装而来,包含requests库的所有功能,增加了“数据清洗”和“Ajax数据动态渲染功能
扩展库安装:pip install requests-html
扩展库导入:from requests-html import HTMLSession
http请求方式:
session = HTMLSession()
response = session.get(r'https://xxxxxx)
selenium
基本语法
网页元素定位
id
name
class_name
tag_name(网页html标签)
link_text(精确超链接文本查找)
partial_link_text(模糊超链接查找)
xpath
css_selector
模拟登录
模拟登录
requests-html
自动登录(cookie)
p, li { white-space: pre-wrap; } import requests_htmlsession = requests_html.HTMLSession()# 访问时带上身份信息,自动登录时身份信息存储在cookie里边# 方式1-1. 获取cookie,通过浏览器开发者工具,分析每次访问网络地址时,带的cookie,拿来直接使用。cookie_str = 'e2=%7B%22pid%22%3A%22qd_P_my_bookshelf%22%2C%22eid%22%3A%22qd_M192%22%2C%22l1%22%3A3%7D; e1=%7B%22pid%22%3A%22qd_P_my_bookshelf%22%2C%22eid%22%3A%22qd_M01%22%2C%22l1%22%3A1%7D; _csrfToken=zJblojyPuC8lLR0QxikKCq4tIcWZLFCS4OPDUpPc; newstatisticUUID=1611663733_564709198; ywguid=854019865710; ywkey=yw8mya8Rl9Oz; ywopenid=BA0FB0705F583AF6036BF9061AF57A6D; e1=%7B%22pid%22%3A%22qd_P_mycenter%22%2C%22eid%22%3A%22qd_M02%22%2C%22l1%22%3A1%7D; e2=%7B%22pid%22%3A%22qd_P_all%22%2C%22eid%22%3A%22qd_A08%22%2C%22l1%22%3A1%7D'# 将浏览器获得的cookie转化为字典形式cookies = {item.split('=')[0]: item.split('=')[1] for item in cookie_str.split(';')}#res = session.get('https://my.qidian.com/bookcase', cookies=cookies)# 方式1-2 将分析出来的cookie信息request请求头部,通过头部带到服务器headers = { 'cooki': 'e2=%7B%22pid%22%3A%22qd_P_my_bookshelf%22%2C%22eid%22%3A%22qd_M192%22%2C%22l1%22%3A3%7D; e1=%7B%22pid%22%3A%22qd_P_my_bookshelf%22%2C%22eid%22%3A%22qd_M01%22%2C%22l1%22%3A1%7D; _csrfToken=zJblojyPuC8lLR0QxikKCq4tIcWZLFCS4OPDUpPc; newstatisticUUID=1611663733_564709198; ywguid=854019865710; ywkey=yw8mya8Rl9Oz; ywopenid=BA0FB0705F583AF6036BF9061AF57A6D; e1=%7B%22pid%22%3A%22qd_P_mycenter%22%2C%22eid%22%3A%22qd_M02%22%2C%22l1%22%3A1%7D; e2=%7B%22pid%22%3A%22qd_P_all%22%2C%22eid%22%3A%22qd_A08%22%2C%22l1%22%3A1%7D'}res = session.get('https://my.qidian.com/bookcase', headers=headers)#print(res.text)# 方式2.每次登录自动获取最新的存储在本地电脑的cookie信息# cookie_util 安装# 数据清洗、数据解析,获得所需的信息rows = res.html.xpath("//table[@id='shelfTable']/tbody/tr")for row in rows: #进一步缩小范围,针对每一行进行更精确的查找 element_titles = row.xpath("//span[@class='shelf-table-name']/b/a[2]") #获取的数据为一个集合 element_authors = row.xpath('//td[@class="col4"]/a[1]') print(element_titles[0].text +' : ' +element_authors[0].text)
数据清洗
正则表达式 re
import requests import re # 正则表达式库 import time # 时间 # 1.爬取网页HTML源代码 def search_qidian(page): list = range(1, page+1) list_result = [] for i in list: res = requests.get("https://www.qidian.com/rank/yuepiao?page=" + str(i)) # 指定需要爬取的页码 # time.sleep(2) # 设置休息时间,保证交互顺利完成再进行下一步。确保HTML的结构完整。 # 2.定义正则表达式的模式(pattern),寻找我们需要提取数据的规律 # 缩小范围,只抓取我们需要的内容 pattern = r'<div class="book-img-text">(.*)</ul>' # 其中'.'表示任意字符,'*'表示0次或者多次重复。'()'代表正则表达式的查找组。 result = re.search(pattern, res.text) # 从res.text中按照匹配pattern规则,返回符合pattern规则的内容。 # with open(r'E:\G.Program\VscodeProje\学习\爬虫\result.html','w',encoding='utf-8') as f: #输出文件内进行产看,确保选取内容正常。 # f.write(result.group(1)) # f.flush() text = result.group(1) # 缩小范围后的HTML代码包含我们需要的小说信息 # 再次使用正则表达式对结果进行筛选。 pattern1 = r'<h4><a .*?>(.*?)</a></h4>' # (.*?)非贪婪模式,可以尽可能多的获取内容。 result1 = re.findall(pattern1,text) # findall:一次可以找出多个符合匹配的内容。 list_result.append(result1) result2 = [a for b in list_result for a in b] # 列表推导式打开列表,去掉列表嵌套。 for iteam in result2: print('第%s:%s'%(result2.index(iteam)+1, iteam)) # 格式化输出结果 if __name__ == "__main__": # main函数 search_qidian(5) # 输入需要爬取的页码数量
扩展库:import re
原理:html看作“字符串”
操作步骤
获取html代码 requests.get(url=‘******’)
定义正则表达式模式(pattern) 分析html字符串,找出组织规律
提取内容 re.search() / re.findall() 提取符合模式的内容
XPath
p, li { white-space: pre-wrap; } import requestsfrom lxml import etreeimport timedef search(page): # 1.抓取网页的html代码 html_element = requests.get('https://www.qidian.com/rank/yuepiao?page='+str(page)) time.sleep(1) # d等待一下,保证信息get完整 html = html_element.text # 转换字符串格式 # 2.通过xpath获取所需内容 t = etree.fromstring(html, etree.HTMLPullParser()) ranks = t.xpath("//div[@class='book-img-box']/span/text()") # //表示任意子节点,text()表示提取文字信息 titles = t.xpath("//div[@class='book-mid-info']/h4/a/text()") # [@]内部表示目录的属性 authous = t.xpath("//div[@class='book-mid-info']/p[@class='author']/a[1]/text()") categories = t.xpath("//div[@class='book-mid-info']/p[@class='author']/a[2]/text()") # [1]括号内数字表示位置索引 update = t.xpath("//div[@class='book-mid-info']/p[@class='update']/span/text()") # 3.打印爬取的信息 (快速注释的快捷键 Ctrl+/) for i in range(len(ranks)): print("第%s名: 书名:%s 作者:%s 类别:%s 更新时间:%s"%(ranks[i], titles[i], authous[i], categories[i], update[i]))if __name__ =="__main__": for i in range(5): search(i+1)
扩展库:pip install lxml
导入模块:from lxml import etree
原理:html看作“层次结构的对象”
表达式
/ :从根节点选取(描述绝对路径) /html
// : 不考虑位置,选取页面中所有子孙节点 //div
. : 选取当前节点(描述相对路径) ./div
.. : 选取当前节点的父节点(描述相对路径) h1/../
@属性名 :选取属性的值 @href,@id
text():获取元素中的文本节点 //h1/text()
谓词表达式
//div[@id='msg'] :选取属性id为content的div元素
//div[@class] :选取所有带有属性class的div元素
//div/p[1]/text() :选取div节点中的第一个p元素的文本
//div/p[2]/text() :选取div节点中的第二个p元素的文本
//div/p[last()]/text() :选取div节点中的最后一个p元素的文本
JSON数据
import requests import json html = requests.get('https://u.y.qq.com/cgi-bin/musics.fcg?-=getUCGI5785936585633062&g_tk=5381&sign=zza94ml565vh7ouas9kcf5c04d18943d0ba485b99ac5f3162a6&loginUin=0&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0&data=%7B%22detail%22%3A%7B%22module%22%3A%22musicToplist.ToplistInfoServer%22%2C%22method%22%3A%22GetDetail%22%2C%22param%22%3A%7B%22topId%22%3A4%2C%22offset%22%3A0%2C%22num%22%3A20%2C%22period%22%3A%222021-01-27%22%7D%7D%2C%22comm%22%3A%7B%22ct%22%3A24%2C%22cv%22%3A0%7D%7D') json_str = html.text dic = json.loads(json_str) # 使用json库对json格式进行解析 musics = dic["detail"]["data"]["data"]["song"] for item in musics: print("排名:%s 歌名:%s 歌手:%s"%(item['rank'], item['title'], item['singerName'])) times = dic["detail"]["data"]['songInfoList'] for item in times: print("歌曲时长:%d" % (item['interval']))
扩展库 :import json
JSON 数据的书写格式:名称 : 值对。如: {"name" : "菜鸟教程“, " age“: " 23"}
变量名必须双引号包含,值只有字符串需要双引号包含
json库
json.dumps :将 Python 对象编码成 JSON 字符串
json.loads :将已编码的 JSON 字符串解码为 Python 对象
CSS
p, li { white-space: pre-wrap; } from requests_html import HTMLSessionsession = HTMLSession()res = session.get('https://movie.douban.com/explore#!type=movie&tag=\ %E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0')# print(res.html.html) #第一个html表示返回的网页文件,第二个html表示查看html源代码res.html.render() # 对获取的网页进行渲染,将各部分异步加载的数据,整合成一个整体# 数据清洗,从网页内容软代码中找到我们所需的信息# 1.通过xpath定位我们需要的元素对象result1 = res.html.xpath('//a[@class="item"]/p')# 2.通过CSS表达式定位获取html文档中的对象集合# result2 = res.html.find('a.item>p')# for iteam in result2:# print(iteam.text)# 3.获取电影图片地址,并下载到本地pic = res.html.find('div.cover-wp>img') # 定位并获取所有符合条件的img对象for item in pic: print(item.attrs['src']) # attrs表示对象中含有'='符号的内容,选出相应的字典.图片网络地址,(网络资源,get方式获取/下载) print(item.attrs['alt']) # 电影名称 with open(r'E:\G.Program\pycharm\project\学习\爬虫\pic/' + item.attrs['alt'] + '.jpg', 'bw') as f: f.write(session.get(item.attrs['src']).content)
response.html.find(‘css表达式’) 其中:respnose为requests.get/requests.post方法返回的响应对象
图片下载
p, li { white-space: pre-wrap; } from requests_html import HTMLSessionsession = HTMLSession()res = session.get('https://movie.douban.com/explore#!type=movie&tag=\ %E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start=0')# print(res.html.html) #第一个html表示返回的网页文件,第二个html表示查看html源代码res.html.render() # 对获取的网页进行渲染,将各部分异步加载的数据,整合成一个整体# 数据清洗,从网页内容软代码中找到我们所需的信息# 1.通过xpath定位我们需要的元素对象result1 = res.html.xpath('//a[@class="item"]/p')# 2.通过CSS表达式定位获取html文档中的对象集合# result2 = res.html.find('a.item>p')# for iteam in result2:# print(iteam.text)# 3.获取电影图片地址,并下载到本地pic = res.html.find('div.cover-wp>img') # 定位并获取所有符合条件的img对象for item in pic: print(item.attrs['src']) # attrs表示对象中含有'='符号的内容,选出相应的字典.图片网络地址,(网络资源,get方式获取/下载) print(item.attrs['alt']) # 电影名称 with open(r'E:\G.Program\pycharm\project\学习\爬虫\pic/' + item.attrs['alt'] + '.jpg', 'bw') as f: f.write(session.get(item.attrs['src']).content)
requests/requests-html库
基于open()存储图片到本地(自己电脑)
requests.get(‘图片url地址’) / session.get(‘图片url地址’)
数据文档存储
csv
import csv #内置库
Excel
import xlwings #第三方库,需安装
Word
import docx #第三方库,需安装