爬虫的分类:
通用:
聚焦:数据解析
增量式:监测
http:客户端和服务器端进行数据交互的形式
证书密钥加密:
什么是证书?
证书种包含的是经过数字签名的公钥
反爬:
robots
UA伪装
请求载体的身份标识
在headers种应用一个字典(请求头信息:UA)
动态加载的数据
如何处理动态请求参数:
封装到一个字典中,字典需要作用到data或者params

  • 编码的流程

    • 指定url
    • 发起请求
    • 获取响应数据
    • 数据解析
    • 持久化存储
  • 数据解析的作用
    • 用于获取页面中局部的页面源码数据
  • 如何实现数据解析
    • 正则
    • bs4(独有)
    • xpath(最为通用)
    • pyquery
  • 数据解析的通用原理是什么?
    • 标签定位
    • 将标签中间存储的文本数据或者其属性值进行捕获

正则解析

  • 需求:爬取糗事百科中的图片数据

    • 确认了页面中没有动态加载数据的存在

#爬取糗事百科
# re正则匹配
import requests
import re
import os
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}

dirname="./qiutu"
# 创建文件夹
if not os.path.exists(dirname):
os.mkdir(dirname)

url="https://www.qiushibaike.com/imgrank/page/%d/"

for page in range(1,3):
print("开始下载第{}页图片".format(page))
#指定新的url
new_url=format(url%page)

#获得源码文本信息
page_text=requests.get(url=new_url,headers=headers).text

ex='<div class="thumb">.*?<img src="(.*?)" alt=.*?</div>'
# 获取图片地址 注意re.S
img_src_list=re.findall(ex,page_text,re.S)

for img_src in img_src_list:
new_img_src='https:'+img_src
img_name=img_src.split("/")[-1]
img_path=dirname+"/"+img_name
img_text=requests.get(url=new_img_src,headers=headers).content

with open(img_path,"wb") as f:
f.write(img_text)
print(img_name,"下载完毕!")

# 方法2:
# from urllib import request
# request.urlretrieve(new_img_src,img_path)

# <div class="thumb">

# <a href="/article/121911520" target="_blank">
# <img src="//pic.qiushibaike.com/system/pictures/12191/121911520/medium/S4TSN79VOC3G0R83.jpg" alt="糗事#121911520" class="illustration" width="100%" height="auto">
# </a>
# </div

bs4解析

  • 环境的安装:

    • pip install bs4
    • pip install lxml
  • bs4解析原理
    • 实例化一个BeautifulSoup的对象,且将即将被解析的页面源码加载到该对象中
    • 使用该对象中的属性或者方法进行标签定位和数据提取
  • BeautifulSoup对象的实例化方式:lxml就是一款解析器
    • BeautifulSoup(fp,'lxml'):将本地存储的html文档加载到该对象中
    • BeautifulSoup(page_text,'lxml'):将互联网上获取的html源码加载到该对象中
from bs4 import BeautifulSoup
import lxml
fp=open("./bs.html",'r',encoding="utf-8")
soup=BeautifulSoup(fp,"lxml")
soup

# 标签定位# soup.tagName:返回的就是页面中第一次出现的tagName标签(返回的是一个单数)# soup.title
# soup.div# find函数的用法:属性定位
# soup.find('tagName',attrName='value')
# 注意:返回的是单数soup.find('div',class_="song")# soup.find_all('tagName'):定位所有的tagName的标签
# soup.find_all('tagName',attrName='value'):属性定位
# 注意:返回值是列表# soup.find_all("div")
# soup.find_all("div",class_="song")# select('选择器'):根据选择器进行标签定位且返回的是复数(列表)
# 类选择器,id选择器,标签选择器,层级选择器
# 层级选择器:>表示一个层级,空格表示多个层级# soup.select(".song > p")[0]
# soup.select(".tang > ul > li")
# soup.select(".tang li")# 取数据(属性值和标签中存储的文本数据)# text 和 string 的区别:
#  string  获取的是标签中直系的文本内容
#  text 获取标签中所有的文本内容# soup.p.string
# soup.p.text# 取属性:
# tag['attrName']# soup.select("div > a")[0]["href"]
# for a in soup.select(".tang > ul > li > a"):
#     print(a["href"])

使用流程:       - 导包:from bs4 import BeautifulSoup- 使用方式:可以将一个html文档,转化为BeautifulSoup对象,然后通过对象的方法或者属性去查找指定的节点内容(1)转化本地文件:- soup = BeautifulSoup(open('本地文件'), 'lxml')(2)转化网络文件:- soup = BeautifulSoup('字符串类型或者字节类型', 'lxml')(3)打印soup对象显示内容为html文件中的内容基础巩固:(1)根据标签名查找- soup.a   只能找到第一个符合要求的标签 - soup.div  只能找到第一个div标签(2)获取属性- soup.a.attrs  获取a所有的属性和属性值,返回一个字典- soup.a.attrs['href']   获取href属性- soup.a['href']   也可简写为这种形式(3)获取内容- soup.a.string   # string获取的是标签中直系的文本内容- soup.a.text   # text获取的是当前标签下所有文本内容,包括子标签- soup.a.get_text()【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容(4)find:找到第一个符合要求的标签- soup.find('a')  找到第一个符合要求的- soup.find('a', title="xxx")  获取title=xxx的第一个标签- soup.find('a', alt="xxx")   h获取alt=xxx的第一个标签- soup.find('a', class_="xxx")  ...- soup.find('a', id="xxx")   ...(5)find_all:找到所有符合要求的标签- soup.find_all('a')- soup.find_all(['a','b']) 找到所有的a和b标签- soup.find_all('a', limit=2)  限制前两个(6)根据选择器选择指定的内容- soup.select('#tang')- 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器- 层级选择器:select(".tang li") #class=tang标签下面的所有li标签,包含所有层级div > p > a > .lala   # 只能是下面一级【注意】select选择器返回永远是列表,需要通过下标提取指定的对象总结:层级选择器定位返回总是一个复数(列表)类选择器,id选择器,标签选择器,层级选择器层级选择器:>表示一个层级,空格表示多个层级

爬取三国演义小说

url = 'http://www.shicimingju.com/book/sanguoyanyi.html'
page_text = requests.get(url=url,headers=headers).text#使用bs4进行数据解析(章节标题&内容)
soup = BeautifulSoup(page_text,'lxml')
a_list = soup.select('.book-mulu > ul > li > a')
fp = open('sanguo.txt','w',encoding='utf-8')
for a in a_list:title = a.stringdetail_url = 'http://www.shicimingju.com'+a['href']#对详情页的url发起请求解析出章节内容detail_page_text = requests.get(url=detail_url,headers=headers).textdetail_soup = BeautifulSoup(detail_page_text,'lxml')content = detail_soup.find('div',class_='chapter_content').textfp.write(title+':'+content+'\n')print(title,'保存成功!!!')
fp.close()

xpath

xpath解析

  • 环境安装:pip install lxml
  • 解析原理:
    • 实例化一个etree类型的对象,且将即将被解析的页面源码数据加载到该对象中
    • 调用该对象中的xpath方法结合着不同的xpath表达式进行标签定位和数据提取
  • 实例化对象:
    • etree.parse(fileName)
    • etree.HTML(page_text)
from lxml import etree
tree=etree.parse('bs.html')# 属性定位
# tree.xpath('//div[@class="song"]')
# 索引定位
# 索引值是从1开始
# 在xpath表达式中非最左侧的/和//的区别?
# /表示一个层级
# //表示多个层级
# tree.xpath("//div[@class='song']//text()")# 取文本
# /text():获取的是标签下直系的文本数据
# //text():获取的是标签下所有的文本数据

# tree.xpath("//div[@class='song']/p[1]/text()")# tree.xpath("//div[@class='song']//a[1]/span/text()")# 取属性# tree.xpath("//div[@class='song']//img/@src")

基于标签定位:tree.xpath('/html/head/meta')tree.xpath('//meta')xpath表达式中最左侧的/和//的区别是什么?
/表示我们必须从根标签进行定位
//表示我们可以从任意位置标签定位

属性定位:#找到class属性值为song的div标签//div[@class="song"]
层级&索引定位:#找到class属性值为tang的div的直系子标签ul下的第二个子标签li下的直系子标签a//div[@class="tang"]/ul/li[2]/a
tree.xpath('//div[@class="tang"]/ul/li[3]')  tree.xpath('//div[@class="tang"]//li[3]') # 与上一条属性索取为相同结果在xpath表达式中非最左侧的/和//的区别?/表示一个层级//表示多个层级
逻辑运算:#找到href属性值为空且class属性值为du的a标签//a[@href="" and @class="du"]
模糊匹配://div[contains(@class, "ng")]//div[starts-with(@class, "ta")]
取文本:# /表示获取某个标签下的文本内容# //表示获取某个标签下的文本内容和所有子标签下的文本内容//div[@class="song"]/p[1]/text()//div[@class="tang"]//text()
取属性://div[@class="tang"]//li[2]/a/@href

# 爬取boss中的岗位信息(岗位名称,薪资,公司名称,岗位描述)
import requests
from lxml import etree
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}url="https://www.zhipin.com/c101010100/?query=python后端&page=%d"fp=open("boss.txt","w",encoding="utf-8")for page in range(1,4):new_url=format(url%page)page_text=requests.get(url=new_url,headers=headers).texttree=etree.HTML(page_text)
#     获取工作列表li_list=tree.xpath("//div[@class='job-box']/div[@class='job-list']/ul/li")for li in li_list:job_title=li.xpath("./div//h3[@class='name']/a/div[1]/text()")[0]salary=li.xpath("./div//h3[@class='name']/a/span/text()")[0]company=li.xpath("./div/div[2]/div/h3/a/text()")[0]#         详细信息网页detail_url='https://www.zhipin.com' + li.xpath('./div/div[1]/h3/a/@href')[0]detail_text=requests.get(url=detail_url,headers=headers).textdetail_tree=etree.HTML(detail_text)desc=detail_tree.xpath('//*[@id="main"]/div[3]/div/div[2]/div[2]/div[1]/div/text()')desc=''.join(desc)fp.write(job_title+":"+"\n"+salary+"\n"+company+"\n"+desc)
fp.close()

# 处理中文乱码问题
# url = 'http://pic.netbian.com/4kmeinv/index_%d.html'import requests
from lxml import etree
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}fp=open('meinv.txt','w',encoding='utf-8')for page in range(1,4):if page==1:url="http://pic.netbian.com/4kmeinv/"else:url="http://pic.netbian.com/4kmeinv/index_{}.html".format(page)response=requests.get(url=url,headers=headers)#     解决中文乱码方式1  耗资源 不推荐
#     response.encoding='gbk'page_text=response.texttree=etree.HTML(page_text)li_list=tree.xpath('//*[@id="main"]/div[3]/ul/li')for li in li_list:img_name=li.xpath("./a/b/text()")[0]#     解决中文乱码方式2img_name=img_name.encode("iso-8859-1").decode("gbk")img_url='http://pic.netbian.com' +  li.xpath('./a/img/@src')[0]fp.write(img_name+":"+img_url+"\n")fp.close()

# 增强xpath表达式的通用性  ****采用管道符
# url="https://www.aqistudy.cn/historydata/"
# 获取热门城市与普通城市的城市名  import requests
from lxml import etree
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}url="https://www.aqistudy.cn/historydata/"response=requests.get(url=url,headers=headers)
page_text=response.texttree=etree.HTML(page_text)
# hot_city=tree.xpath('//div[@class="hot"]//div[@class="bottom"]/ul/li/a/text()')
# print(hot_city)
# all_city=tree.xpath('//div[@class="all"]//div[@class="bottom"]/ul/div[2]/li/a/text()')
# print(all_city)# cities=tree.xpath('//div[@class="hot"]//div[@class="bottom"]/ul/li/a/text() | //div[@class="all"]//div[@class="bottom"]/ul/div[2]/li/a/text()')
# print(cities)# cities=tree.xpath('//div[@class="all"]//div[@class="bottom"]/ul/div[2]/li/a/text() | //div[@class="hot"]//div[@class="bottom"]/ul/li/a/text()')
# print(cities)

举例

# 糗事百科的段子内容和作者(xpath的管道符)名称进行爬取,然后存储到mysql中or文本import requests
from lxml import etree
import osheaders={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}dirName='./homework'
if not os.path.exists(dirName):os.mkdir(dirName)filepath=os.path.join(dirName,"qiubai.txt")        fp=open(filepath,'w',encoding="utf-8")
# 指定url
url='https://www.qiushibaike.com/text/page/%d/'for page in range(1,10):print("开始下载第{}页".format(page))new_url=format(url%page)#     发送请求 获取数据response=requests.get(url=new_url,headers=headers)page_text=response.texttree=etree.HTML(page_text)info_list=tree.xpath('//div[@id="content-left"]/div')for info in info_list:
#         管道符号获取所有用户user_name=info.xpath("./div[1]/a[2]/h2/text() | ./div[1]/span[2]/h2/text()")[0]content=info.xpath("./a[1]/div/span/text()")content=''.join(content)qiubai=user_name.strip()+":"+content.strip()+"\n\n"fp.write(qiubai)
fp.close()
print("下载完毕!")

# http://sc.chinaz.com/jianli/free.html爬取简历模板

import requests
from lxml import etree
import os
import time
import randomheaders={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}dirName='./homework'
if not os.path.exists(dirName):os.mkdir(dirName)for page in range(1,3):if page==1:url='http://sc.chinaz.com/jianli/free.html'else:url='http://sc.chinaz.com/jianli/free_{}.html'.format(page)page_text=requests.get(url=url,headers=headers).texttree=etree.HTML(page_text)a_list=tree.xpath('//div[@id="container"]/div/a/@href')
#     print(a_list)for a in a_list:detail_text=requests.get(url=a,headers=headers).textdetail_tree=etree.HTML(detail_text)#         下载路径a_detail=detail_tree.xpath('//*[@id="down"]/div[2]/ul/li[1]/a/@href')[0]
#         print(a_detail)filename=detail_tree.xpath('//div[@class="ppt_left fl"]//h1//text()')[0]#     识别中文filename1 = filename.encode("iso-8859-1").decode("utf-8")+'.rar'print(filename1)response=requests.get(url=a_detail,headers=headers)file_content=response.contentfilepath=os.path.join(dirName,filename1)print(filepath)with open(filepath,'wb') as f:f.write(file_content)time.sleep(random.randint(1,3))print("ok1111111111111")
print("ok")

开线程池# http://sc.chinaz.com/jianli/free.html爬取简历模板
from concurrent.futures import ThreadPoolExecutor
import requests
from lxml import etree
import os
import time
import random
print("start")
start=time.time()
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
}dirName = './homework'
if not os.path.exists(dirName):os.mkdir(dirName)
url_dic={}
for page in range(1, 3):if page == 1:url = 'http://sc.chinaz.com/jianli/free.html'else:url = 'http://sc.chinaz.com/jianli/free_{}.html'.format(page)page_text = requests.get(url=url, headers=headers).texttree = etree.HTML(page_text)a_list = tree.xpath('//div[@id="container"]/div/a/@href')#     print(a_list)for a in a_list:detail_text = requests.get(url=a, headers=headers).textdetail_tree = etree.HTML(detail_text)#         下载路径a_detail = detail_tree.xpath('//*[@id="down"]/div[2]/ul/li[1]/a/@href')[0]#         print(a_detail)filename = detail_tree.xpath('//div[@class="ppt_left fl"]//h1//text()')[0]#     识别中文filename1 = filename.encode("iso-8859-1").decode("utf-8") + '.rar'url_dic[filename1]=a_detail# response = requests.get(url=a_detail, headers=headers)# file_content = response.content## filepath = os.path.join(dirName, filename1)# # print(filepath)# with open(filepath, 'wb') as f:#     f.write(file_content)# # time.sleep(random.randint(1, 3))
print(url_dic)def get_html(name,url):res=requests.get(url,headers=headers)return {"name":name,"content":res.content}def parser_page(ret_obj):dic=ret_obj.result()with open(dic['name'], 'wb') as f:f.write(dic['content'])
t=ThreadPoolExecutor(30)for name in url_dic:task=t.submit(get_html,name,url_dic[name])task.add_done_callback(parser_page)print("ok",time.time()-start)

转载于:https://www.cnblogs.com/XLHIT/p/11297463.html

爬虫 正则 bs4 xpath 中文乱码 管道符相关推荐

  1. python学习笔记分享(四十)网络爬虫(7)反爬虫问题,解决中文乱码,登陆和验证码处理

    网络爬虫深度知识 一.反爬虫问题 (一)反爬虫原因 1.网络爬虫浪费了网站的流量 2.数据是私有资源 3.爬虫协议与原则 (二)反爬虫方式 (三)反反爬虫 1.原理 2.三种方法 二.解决中文乱码 ( ...

  2. pycharm爬虫打印网页出现中文乱码问题

    pycharm爬虫打印网页出现中文乱码问题 今天爬了一天的微博,到现在还没有成功.期间也出现了打印页面中文显示乱码问题. html=session.get(url) print(html.text) ...

  3. python爬虫中文乱码_Python 爬虫过程中的中文乱码问题

    python+mongodb 在爬虫的过程中,抓到一个中文字段,encode和decode都无法正确显示 注:以下print均是在mongodb中截图显示的,在pythonshell中可能会有所不同 ...

  4. 盘点3种Python爬虫 中文乱码 的处理方法

    人生苦短,快学Python! 给大家祭出网络爬虫过程中三种中文乱码的处理方案,希望对大家的学习有所帮助. 前言 前几天有个粉丝在Python交流群里问了一道关于使用Python网络爬虫过程中中文乱码的 ...

  5. 爬虫常用数据提取方式:正则、xpath、beautifulsoup

    文章目录 1.正则re 2.xpath 2.1 定位 2.1.1 xpath中选取节点的路径表达式 2.1.2 xpath谓语,即[ ]中的内容 2.1.3 选取未知节点 2.1.4 选择多个路径 2 ...

  6. 爬虫学习二: bs4 xpath re

    欢迎关注datawhale:http://www.datawhale.club/ 2.1 Beautiful Soup库入门 目标: 2.1.1 Beautiful Soup库的基本元素 2.1.2 ...

  7. Python 爬虫数据写入csv文件中文乱码解决以及天眼查爬虫数据写入csv

    python爬虫数据写入csv文件中文乱码,用'utf-8'在pycharm中打开文件没有问题,但是用excel打开却出现了问题,以下为解决方法. (最近在练习爬虫,这个博文是对自己学习的记录和分享, ...

  8. Python 爬虫 中文乱码一文通

    如果经常使用Python编程或者是其他语言编程,或者在前面的文章中已经多次使用Python练习网络爬虫技术,就不可避免地会遇到中文乱码的问题.中文乱码问题经常难以理解,或者治标不治本,本文就是来解决这 ...

  9. 爬虫学习----解决中文乱码

    一.字符编码 在编程的过程中,我们会遇到中文乱码的问题.要解决中文乱码我们就要了解计算机的字符编码,计算机有很多编码方式,因为计算机只能处理数字,因为处理文本的话,就必须先转化为数字.最早的时候计算机 ...

最新文章

  1. opencv python下载_[福利] OpenCV4 Python 最新中文版官方教程来了(附下载)
  2. Linux find
  3. 十二、“最是真心藏不住,一言一语总关情。”(2021.2.11)
  4. VTK:检查VTK的版本用法实战
  5. Ubuntu16.04用源安装Nginx+PHP5.6+MySQL5.6
  6. B - Ada and Queue
  7. i7 5500u linux,i7 5500u相当于什么cpu
  8. msp430单片机 温度计编程_MSP430系列与89C5l系列的比较
  9. idea 快捷键代码行标记并快捷跳到标记行
  10. oracle 创建更新定时任务,oracle 创建定时任务
  11. javascript基础学习
  12. 比特币在推特上的活跃度正接近2017年水平
  13. 问题:'NoneType' object has no attribute 'encoding'
  14. WORD 同一位置连续引用多个参考文献编辑技巧
  15. 【python】语义分割(标签)黑色(单通道)图片的读取和显示方法
  16. mysql contain和like_mysql不带%的like 与等号之间的区别
  17. 为什么win10开热点后电脑没有网络?
  18. UTM坐标系与GPS坐标系转换笔记
  19. 台式计算机如何双屏显示,台式计算机如何同时连接显示器和电视双屏显示器?...
  20. Xubuntu22.04增加快捷键

热门文章

  1. javascript 关键字this
  2. javascript设计模式系列
  3. opengl笔记—— glMultMatrixf() 区别 glLoadMatrixf()
  4. 考研英语真题笔记 2020
  5. 【MyBatis笔记】09-一对多关系建表
  6. 数据分析方法(一):对比与对标
  7. android系统图标大小
  8. 全球英文经典演讲100篇_日语演讲100问(1)即兴演讲不即兴!(理论篇)
  9. php怎么取json数组元素个数,json,数组_取出json数据中的某一项组成一个数组?,json,数组,php - phpStudy...
  10. vue表格刷新数据_Vue.js的列表数据的同步更新方法