爬虫【网页构造+第三方库+爬取逻辑示例+正则表达式+xpath+多进程】

基本语法

构造url网页链接常用字符串处理
str.split('.')#不添加默认按空格tab分割'www.baidu.com'-->'www','baidu','com'
str.replace('要修改的','要用来替代的')
str.strip()#去掉前后端(两侧)空格
'{提取的格式化内容}str'.format('选项')#常用在连接最后的搜索内容'https://www.pexels.com/search/{}/'format(content)
函数
#手机号隐私展示:156****9354(输入时完整)
hiding_num=num.replace(number[3:7],'*'*4)
数据结构
列表

列表在爬虫中的常见作用:构造多个URL,爬取的数据,大多数都为列表数据结构
特性:每个元素都是可变的,有序,可以容纳所有对象[字符串,整数,浮点数,元组,函数,布尔值,集合等];列表的增删改查在爬虫中用的少

常用多重循环

zip前后变量要一致

names=['小a''小b','小c']
ages=[12,13,14]
for name,age in zip(names,ages):
	print(name,age)
#result 		小a 12 			#小b 13 		#小c 14

请求多个网页,通常情况下会把网页存到列表中,循环依次取出并访问爬取数据,手动存入花费时间,代码冗余,通过列表推导式构造列表

http://bj.xiaozhu.com/search-duanzufang-p1-0
http://bj.xiaozhu.com/search-duanzufang-p2-0
http://bj.xiaozhu.com/search-duanzufang-p3-0
......
urls=['http://bj.xiaozhu.com/search-duanzufang-p{}-0'.format(number)for num in range(1,14)]
for url in urls:
	print(url)

字典:插入MongoDB数据库需用字典结构
元组(不能修改只能查看)和{集合}很少用到

文件操作
open(name[,model[,buffering]])	#文件名作为唯一强制参数
r w a b +	#model模式
f=open('.....路径....','w+')
f.write()	#写入
content=f.read()#清理缓冲和文件安全	#读取
面向对象
class Bike:
	compose=['frame','wheel','pedal']
my_bike=Bike()	#类的实例化 my_bike 类的实例
your_bike=Bike()
print(my_bike.compose) #'.'加上类的属性,类属性的引用
print(your_bike.compose)
my_bike.other='basket' #给类的实例属性进行赋值,实例属性
print(my_bike.other)	
#实例方法:方法就是函数,方法是对实例进行使用的,所以又叫实例方法,对bike类而言,它的方法就是骑行。
class Bike:
#----------------实例方法--------------
	compose=['frame','wheel','pedal']
	def use(self):#self参数就是实例本身,可以有参数
		print('u r riding')#对实例进行使用的,实例方法
	my_bike=Bike()
	my_bike.use()#实例方法
#----------------实例方法可以添加参数-----------
	def use(self,time):
		print('u ride {}m'.format(time*100))
	my_bike=Bike()
	my_bike.use(10)
#-------__init__()创造实例时,不需要引用也会被自动执行---------
class Bike:
	compose=['frame','wheel','pedal']
	def __init__(self):
		self.other='basket'
	def use(self,time):
		print('u ride {}m'.format(time*100))
	my_bike=Bike()
	print(my_bike.other)
继承

2nd 爬虫原理和网页构造

网络连接:基本过程
爬虫原理:基本原理和过程
chrome浏览器:使用chrome认识网页结构和查询网页信息

网络连接

计算机(购买者)带着请求头和消息体(硬币和所需饮料)向服务器(自动售货机)发起依次request请求(购买),响应的服务器(自助售货机)返回本计算机相应的HTML文件作为Response(相应的商品)
request (请求头&请求体)
response (HTML文件)

爬虫原理

爬虫要做的两件事:

  1. 模拟计算机对服务器发起的Request请求
  2. 接收服务端的response内容并解析,提取所需的信息
    一次请求回应不能批量获取数据–>设计爬虫流程(多页面 / 跨页面)
    多页面:
    1.手动翻页并观察各网页的URL构成特点,构造出所有页面的URL存入列表中
    2.根据URL列表依次循环取出URL
    3.定义爬虫函数
    4.循环调用爬虫函数,存储数据
    5.循环完毕,结束爬虫程序
    【插图】
    跨页面
    1.定义爬取函数爬取列表页的所有专题的URL
    2.将专题URL存入列表中(种子URL)
    3.定义爬取详细页面数据函数
    4.进入专题详细页面爬取详细页数据
    5.存储数据,循环完毕,结束爬虫程序

网页构造

简单介绍网页构造,前段语法不做解释:
HTML文件;CSS样式;的是JavaScript代码
客户浏览的网页是浏览器渲染后的结果,浏览器就像翻译官,把HTML,CSS和JavaScript代码翻译后得到用户使用的网页界面。网页是房子,HTML是框架和格局(几室几厅),CSS就是样式(地板,房漆),JavaScript是里面的电器。

1st爬虫程序

Python第三方库:概念及安装方法
Requests库:使用原理和方法
BeautifulSoup库:使用原理和方法
Requests和BeautifulSoup的组合

python第三方库

(不用底层思想,用最少的代码写最多的功能,不用铁矿石橡胶造车,只用拼装)
File /project setting

Requests:请求网站获取网页数据

import request
res=requests.get('http://bj.xiaozhu.com/')
print(res)
#结果为<Response [200]>,说明请求成功,若404 400 失败
print(res.txt)#打印源代码

伪装请求头User-Agent F12代开开发者工具,刷新网页后找到User-Agent进行复制Mozilla/5.0

import Requests
headers={User-Agent:'Mozilla/5.0'}
res=requests.get('http://bj.xiaozhu.com',headers-headers)
print(res.text)

Requests库
不仅有get方法,还有post方法(用于提交表单来爬取需要登陆才能获得数据的网站)
Requests常见错误异常:
1.ConnectionError异常,网络问题(DNS查询失败,拒绝链接等)
2.Response.raise_for_status()抛出一个HTTPError异常,原因为HTTP请求返回了不成功的状态码(网页不存在,返回404错误)
3.Requests抛出一个Timeout异常,原因为请求超时
4.Requests抛出一个TooManyRedirects异常,请求超过设定的最大重定向次数
requests.exceptions.RequestException当发现这些错误或异常进行代码修改重新再来时,爬虫的程序又重新开始运行,数据重新爬取,对于效率和质量来说都是不利的。通过try避免异常

import Requests
headers={User-Agent:'Mozilla/5.0'}
res=requests.get('http://bj.xiaozhu.com',headers-headers)
try:
	print(res.text)
except ConnectionError: #出现错误会执行下面的操作
	print('拒绝连接')

通过try和except,如果请求成功了,会打印网页的源代码。如果connectionError异常,打印‘拒绝连接’,这样程序就不会报错,而是给编程一个提示,不会影响下面代码的运行。

BeutifulSoup库

主要功能:把源代码解析为Soup文档,以便过滤提取数据

import requests
from bs4 import BeautifulSoup
headers={'User-Agent':'Mozilla/5.0'}
res=requests.get('http://bj.xiaozhu.com/',headers=headers)
soup=BeautifulSoup(res.text,'html.parser')#对返回的结果进行解析
print(soup.prettify())
#看上去类似,但是标准缩进,为结构化的数据,为数据的过滤提取做好准备

支持HTML解析器外,还支持一些3rd方解析器。
解析得到的Soup文档可以用==find() find_all() selector()==方法定位需要的元素

find_all(tag,attributes,recursive,text,limit,keywords)	#返回集合
soup.find_all('div',"item")##查找div标签,class="item"
soup.find_all('div',class="item")
soup.find_all('div',attrs={"class":"item"})#attrs参数定义一个字典参数

find(tag,attributes,recursive,text,keywords)	#返回一个

soup.selector(div.item > a > h1) #括号内容通过Chrome复制得到 中国 > 湖南省 > 长沙市
#源代码选中元素右击Copy selector 
#page_list > ul > li:nth-child(1) > div.result_btm_con.lodgeunitname > div:nth-child(1) > span > i
print(price.get_text())#从[<i>898</i>]即可获得中间的文字
import requests
from bs4 import BeautifulSoup
headers={'User-Agent':'Mozilla/5.0'}
res=requests.get('http://bj.xiaozhu.com/',headers=headers)
soup=BeautifulSoup(res.text,'html.parser')#对返回的结果进行解析
price=soup.select('page_list > ul > li:nth-child(1) > div.result_btm_con.lodgeunitname > div:nth-child(1) > span > i')
prices=soup.select('page_list > ul > div.result_btm_con.lodgeunitname > div:nth-child(1) > span > i')
print('单个价格:',price )
print('×××××××××××××××××'\n'多个价格:')
for price in prices:
	print(price.get_text())#从[<i>898</i>]即可获得中间的文字

项目1:小猪网页爬取
任务要求: 13页网址;爬取进入详细页面的网址链接,进而爬取数据:标题,地址,价格,房东名称,房东性别,房东头像的链接

代码分析:

  1. 导入Requests BeautifulSoup time
  2. 通过Chrome浏览器开发者工具,复制User-Agent用于伪装浏览器,便于爬虫的稳定性
  3. 定义get_links()函数,获取进入详细页的链接
    传入URL后,进行请求和解析。通过Chrome的检查并Copy Selector,找到进入详细页的URL链接,但URl链接并不是嵌套在标签中,而是在标签属性的信息中
    get_text()获取标签中的文本属性,标签属性通过get('attr ‘)方法获得,URL在href中,用get(’ href ')得到
    最后调用get_info()函数,转入的参数为获取到的网页详细页的链接
  4. get_info()函数,用于获取网页信息并输出信息
    传入URL后,进行请求和解析。通过chrome浏览器的检查并copy selector,获取相应的信息,由于信息数据为列表结构,可以通过多重循环,构造出字典数据,输出并打印出来
  5. judgment_sex()函数,用于判断房东的性别
6. 程序的主入口,通过对网页URL的观察,利用列表的推导式构造13个URL,并一次调用get_links()函数,time.sleep(2)防止请求网页频率过快而导致爬虫失败。

项目2:酷狗TOP500首
思路分析:500首歌一页22首,总共23个URL;排名+歌手+歌曲名+歌曲时间
代码分析:
1.导入需要的库,requests beautifulsoup time
2.伪装User-Agent的header
3.定义get_info()函数,用于获取网页信息并输出;传入URL后,进行请求和解析。通过copy selector获取信息,从列表转换成字典输出打印
4.程序主入口,通过对网页URL的观察,利用列表推导式构造23个URL,并依次调用get_info()函数,time.sleep()防止请求过快被禁

第四章 正则表达式

知识点:正则常用符号,re模块,requests和re的组合
4.1 正则常用功能符号
4.1.1 一般字符
. 匹配任意单个字符 abc aic a&c -->a.b (不包括换行符)
\ 转义字符(特殊含义转字面意思).–>.(而不是匹配所有字符)
[…] 字符集(对应字符集中的任意字符)a[bcd]–>ab ac ad
\d 数字 [0-9]
\D 非数字 [^0-9]
\s 空白(空格,tab,换页符等)[\f\n\r\t\v]
\S 任一非空 [^\f\n\r\t\v]
\w
\W
*
+
?
{m}
{m,n}
^
$
\A
\Z
…没有复制过来完,直接记就行了
4.2 re模块及其用法
4.2.1 search() 第一个符合规则的内容,返回一个正则表达对象
re.match(pattern,string,flags=0)
pattern 匹配的正则表达式
string 要匹配的字符串
flags控制匹配方式,是否区分大小写,多行匹配等

infos=re.search('\d+','one1two2three3')-->#正则表达式对象
print(infos.group())-->1#第一个

4.2.2 sub() 函数(相当于字符串中的replace但是更灵活,能用正则匹配)

re.sub(pattern,repl,string,count=0,flags=0)
re.sub('\D','','123-456-789')#替换非数字

repl 替换的字符串
string 原始字符串
counts 最大次数,默认0替换所有匹配
flags 控制大小写是否区分,多行匹配等
4.2.3 findall()使用频率最多 匹配所有

infos=re.findall('\d+','one1two2three3')-->'1','2','3'
#-----------示例-----------------
import re,requests
res=requests.get('http://bj.xiaozhu.com/')
prices=re.findall('.......')
for price in prices:
	print(price)
#用正则代码更简单,少了解析数据这一步,通过requests库请求的HTML文件就是字符串类型,代码可以直接通过正则表达式提取数据

4.2.4 re模块修饰符
…直接复制记住大小写,多行匹配

a='''<div>指数
</div>'''
word01=re.findall('<div>(.*?)</div>',a)#-->[]
word02=re.findall('<div>(.*?)</div>',a,re.S)#-->['指数\n'] word02.strip()去除换行符
print(word01,word02)

4.3 综合案例 --项目3 爬斗破苍穹 全文小说
技术点:requests库和正则表达式,存储到本地文件
思路分析:2 5 6 7 8–>从第一章开始构造URL,中间有404跳过不爬取,txt存储
代码分析:
1.需要的库 requests re time (正则不用BeautifulSoup解析网页数据)
2.User-Agent请求头伪装
3.新建TXT文档,用于存储文本信息
4.get_info()函数,获取信息并存储信息。传入URL后,进行请求,通过正则表达式定位到小说的文本内容,并写入TXT文档中。
5.程序的主入口,通过对网页URL的观察,使用列表推导式构造所有小说URL,并一次调用get_info()函数,time.sleep()防止访问过快被禁
4.4.综合案例2–爬取糗事百科段子信息
思路分析:提取对应页面的URL特点;需要信息:用户ID,等级,性别,段子文字,好笑数量,评论数量;文件存储在TXT
代码分析:
1.需要的库 requests time re
2.User-Agent (headers)
3.info_lists空列表,用于爬取的数据,字典结构
4.judgement_sex()函数,用于判断用户的性别
5.get_info()获取网页信息传入info_lists列表中。传入URL后,进行请求。以获取用户ID信息为例,通过源代码ctrl+f输入用户ID查看相应位置。信息处理方法有不同。×××××有难度,30号细看联网匹配是否正确
6.主入口,通过列表推导式构造35个URL,并依次调用get_info()函数存入TXT文档

第五章 Lxml库与Xpath语法

etree库 把HTML文档解析为Element对象,输出解析过的HTML文档,会自动修复
lxml比beautifulsoup更快,学会Xpath语法并通过Xpath语法提取所需的网页信息,通过案例 与正则和beautifulsoup的性能对比。

from lxml import etree
text='''
<div class="ui segment">
        piossdfkjawoepuadjf[awpeiwoeihf;asdjgoywuprfiashdfhoew9ufhsdlhfpasudfoiajeohfiaspuefaskhdf;lasjkdf
    </div>
   <div class="ui segment">
        piossdfkjawoepuadjf[awpeiwoeihf;asdjgoywuprfiashdfhoew9ufhsdlhfpasudfoiajeohfiaspuefaskhdf;lasjkdf
    </div>
'''
html=etree.HTML(text)	#-->element
res=etree.tostring(html) 	#解析
from lxml import etree
html=etree.parse('flower.html')
res=etree.tostring(html,pretty_print=True)
print(res)

Xpath语法:在XML文档中查找信息的语言

5.2.1节点关系

父节点

<papa>
	<son></son>
</papa>

子节点
同胞节点
先辈节点
后代节点

5.2.2 节点选择
nodename此节点的所有子节点
/从根节点选取
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
.当前节点
当前节点的父节点
@选取属性
#段子id
'''
获取用户ID
'//div[@class="article block untagged mb15 typs_hot"]'-->每个段落的循环点
//*[@id="qiushi_tag_122191811"]/div[1]/a[2]/h2-->前面循环不用已遍历不用重复,div[1]/a[2]/h2-->用户ID
'''
import requests
from lxml import etree
headers={'User-Agent':'Mozilla/5.0'}
url='http://www.qiushibaike.com/text/'
res=requests.get(url,headers=headers)#通过headers和url用requests.get方法得到响应
selector=etree.HTML(res.text)#用HTML解析响应内容
url_infos=selector.xpath('//div[@class="article block untagged mb15 typs_hot"]')
for url_info in url_infos:
   id=url_info.xpath('div[1]/a[2]/h2/text()')[0]#通过xpath定位用户名的位置
   print(id)

代码思路:
批量爬取的时候,先抓大后抓小,寻找循环点(折叠元素,找到段子完整的信息标签),然后在id完整xpath中删除循环部分,即可以循环的到id
相同字符开头的多个标签:不需要构造多个Xpath,通过starts-with()便可以获取多个标签内容

from lxml import etree
html1='''
<li class="tag-1">需要的内容1</li>
<li class="tag-2">需要的内容2</li>
<li class="tag-3">需要的内容3</li>
'''
selector=etree.HTML(html1)
contents=selector.xpath('//li[starts-with(@class,"tag")]/text()')#要获取的内容的相同之处:属性class以tag开始starts-with的li标签的text
for content in contents:
    print(content)
#------打印结果----
需要的内容1
需要的内容2
需要的内容3

标签嵌套:可以通过string(.)完成

from lxml import etree
html2='''
<div class="red">需要的内容1
    <h1>需要的内容2</h1>
</div>
'''
selector=etree.HTML(html2)
content1=selector.xpath('//div[@class="red"]')[0]
content2=content1.xpath('string(.)')
print(content2)#注意content2就包含了内容1和内容2
#------打印结果----
需要的内容1
    需要的内容2
5.2.4 性能对比(lxml—BeautifulSoup—re)

性能对比项目:糗事百科内容(用户ID,文字信息,好笑数量,评论数量)数据只返回不存储

代码分析:
1.导入对应的库
2.User-Agent
3.构造所有URL
4.定义三种爬虫方法函数
5.程序主入口,通过循环依次调用3种函数,记录开始时间,循环爬取数据,记录结束时间,最后打印出所需时间

爬取方法性能使用难度安装难度使用场景
re困难简单(内置模块)网页结构简单&想要避免额外依赖
BeautifulSoup简单简单爬取数据较少,较慢不影响
Lxml简单相对困难数据大,追求效益时

API

返回JSON或XML格式的数据,而不是HTML

代码分析:
1.requests用于请求网页,lxml和re用于解析爬去网页数据,Pymongo库用于对MongoDB数据库的操作,time降低频率
2.创建MongoDB数据库的集合
3.User-Agent伪装
4.详细页链接的函数,Xpath语法来提取标签中的href信息,最后调用获取爬虫信息get_music_info()函数
5.获取音乐信息的函数,通过Xpath
6.

第八章:多进程爬虫

同一时刻cpu只执行一个进程,不同进程间快速切换,同时运行的感觉。每个线程执行程序的不同部分。
multiprocessing

from multiprocessing import Pool
pool=Pool(processes=4)#创建进程池,设置进程个数
pool.map(func,iterable[,chunksize])#iterable迭代参数例如url
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值