一、requests
requests 模块是爬虫的最重要的部分之一,我们通过这个模块,来获取网页的数据,像我们比如说,要获取某个网页的网页源码,或者是要爬取B站的某个up主的粉丝数,或者你为了能够在一些网站白嫖某些小说,就用到了requests模块,(注:为了获取网页的数据,requests模块并不是唯一的,在python中还有urllib模块,也可以获取网页数据,但是urllib模块相对比较老,且不比requests模块方便,所以作者在这边选择requests模块。)
安装requests 模块
pip install requests
在导入requests模块后,我们就可以使用里面的对象来实现我们的要求。 requests.get(url="...",headers=...):这个函数可以返回我们想要的数据,不过返回的是一个对象,我们要自己定义个对象来承接,然后可以将其重构成我们想要的格式。requests.post(url="...",headers=...,params=...):这个跟get差不多,区别是后面params携带的是你要的参数。(比如你要做一个翻译器,params就可以是你要翻译的内容。)url就是你要爬取的网址,像headers的话,就是用来包装你的爬虫,让你的爬虫伪装成浏览器,(因为大部分的网站,会有反爬机制,他不想让爬虫来爬取自己的内容,所以我们就需要包装一下我们的爬虫。)这样就可以成功爬取网页。
import requests
# headers 可以百度搜索,也可以进入自己的浏览器,F12找到Network下的Name中随便一个地址中的Headers下面
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
}
url = 'https://www.hellorf.com/image/search' #要爬取的网页地址
req = requests.get(url, headers)
print(req.text) #从网页获取的所有内容
二、第三方库 Beautiful Soup
Beautiful Soup: Python 的第三方插件用来提取 xml 和 HTML 中的数据,
安装Beautiful Soup :
pip install bs4
使用例子:
import requests
from bs4 import BeautifulSoup
# headers 可以百度搜索,也可以进入自己的浏览器,F12找到Network下的Name中随便一个地址中的Headers下面
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
}
def get_info_bs4(url):
res = requests.get(url, headers)
soup = BeautifulSoup(res.text, 'html.parser') #解析HTML
# 浏览器在对应内容右键检查,在HTML内容右键 -> copy -> copy selector ,根据实际情况进行修改
# nth-child(3) 表示第三个,爬取全部就删除:nth-child(3)
# #__next > div > main > div > div:nth-child(3) > div > div:nth-child(2) > div > figure > a > img
ranks = soup.select('#rankWrap > div.pc_temp_songlist > ul > li > span.pc_temp_num')
titles = soup.select('#rankWrap > div.pc_temp_songlist > ul > li > a')
times = soup.select('#rankWrap > div.pc_temp_songlist > ul > li > span.pc_temp_tips_r > span')
for rank,title,time in zip(ranks,titles,times):
data = {
'rank': rank.get_text().strip(), # 获取内容并去掉空值
'singer': title.get_text().split('-')[1].strip(),
'song': title.get_text().split('-')[0].strip(),
'time': time.get_text().strip()
}
return data
if __name__=='__main__':
# 获取网页列表
urls = ['https://www.kugou.com/yy/rank/home/{}-8888.html'.format(str(i)) for i in range(1, 24)]
# 遍历列表并进行爬取
for url in urls:
get_info_bs4(url)
三、re正则表达式
re正则表达式是一个强大的功能,python内置,不用下载
正则表达式的元字符
\s :空白符; \S :非空白符; [\s\S] :任意字符; [\s\S]* :0个到多个任意字符; [\s\S]*? : 0个字符,匹配任何字符前的位置;
\d:数字;
\B:非数字 ;
\w:匹配单词 单词等价于:[a-zA-Z0-9_];
\W:匹配非单词;
规则:
. 匹配任意单个字符;
-
匹配前一个字符0次或多次;
-
匹配前一个字符1次或多次;
? 匹配前一个字符0次或一次;
{m} 匹配前一个字符m次;
{m,n} 匹配前一个字符 m - n 次;
{m,} 匹配前一外字符至少 m次 至多无限次;
{,n} 匹配前一个字符 0 到 n次;
\ 转义字符;
[...] 字符集 例:[a-z];
.*? ? +? ?? {}? 使 + 等 变成非贪婪模式
边界匹配(不消耗待匹配的待匹配字符串的字符)
^:匹配字符串开头,在多行模式中匹配每一行的行首;
$:匹配字符串结尾,在多行模式中匹配每一行的行尾;
\b:匹配单词边界,不匹配任何字符,\b匹配的只是一个位置,这个位置的一侧是构成单词的字符,另一侧为非字符、字符串的开始或结束位置,\b是零宽度的。(“单词”是由\w所定义的单词子串) \b相当于:(?<!\w)(?=\w)|(?<=\w)(?!\w);
\B:\b;
\A:仅匹配字符串开头;
\Z:仅匹配字符串结尾;
分组:
| 或,左右表达式任意匹配一个,它先尝试匹配 | 左边的表达式,如果匹配成功则跳过匹配右边的表达式;如果 | 没有被包括在()中,则它在范围是整个正则表达式。
() 分组 ;从表达式左边开始,第遇到一个分组,编号加1;分组表达式作为一个整体,后面可接数量词;分组表达式中的 | 仅在该分组中有效。 例:(abc){3} (abc|def)123 (abc|def){3}123
\number 引用编号为 number 的分组匹配到的字符串。 例:(\d)([a-z])\1\2)
部分匹配函数:
1.search:执行正则表达式搜索并且在搜索结束后返回所匹配到的串,只返回第一次匹配到的结果
2.findall :匹配所有的对象,返回一个列表
上面简单阐述了正则表达式的部分规则,想了解更多需自行去了解
import requests, re
def get_info_re(url):
res = requests.get(url, headers)
#对想要的内容进行匹配。注: re.S 无视换行匹配
ranks = re.findall('<span class="pc_temp_num">(.*?)</span>', res.text, re.S)
titles = re.findall('li class=" " title="(.*?)" data-index="\d*">', res.text, re.S)
times = re.findall('<span class="pc_temp_time">(.*?)</span>', res.text, re.S)
for rank, title, time in zip(ranks, titles, times):
rank = ''.join(re.findall('\d*',rank))
data = {
'rank': rank,
'singer': title.split('-')[0],
'song': title.split('-')[1],
'time': time.strip()
}
return data
if __name__=='__main__':
# 获取网页列表
urls = ['https://www.kugou.com/yy/rank/home/{}-8888.html'.format(str(i)) for i in range(1, 24)]
# 遍历列表并进行爬取
for url in urls:
get_info_re(url)
四、lxml库
安装lxml:pip install lxml
或 pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple
-i 指定下载源
lxml库优点:1.速度快;2.易使用
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点 |
/ | 从当前节点选取直接子节点 |
// | 从当前节点选取子孙节点 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
* | 通配符,选择所有元素节点与元素名 |
@* | 选取所有属性 |
[@attrib] | 选取具有给定属性的所有元素 |
[@attrib='value'] | 选取给定属性具有给定值的所有元素 |
[tag] | 选取所有具有指定元素的直接子节点 |
[tag='text'] | 选取所有具有指定元素并且文本内容是text节点 |
lxml是一个很强大的解析库,这里讲解不多,更多需要自己去深入了解。使用例子:
import requests, time, re
from lxml import html
def get_info_etree(i,url):
res = requests.get(url, headers)
res_etree = html.etree.HTML(res.text) # 解析HTML
# 浏览器在对应内容右键检查,在HTML内容右键 -> copy -> copy xpath ,根据实际情况进行修改
# @: 获取标签里面的class或其他等内容 ; text(): 获取标签里面的元素
in_fos = res_etree.xpath('//*[@id="rankWrap"]/div[2]/ul/li')
for j, in_fo in enumerate(in_fos):
if i==0 and j<3:
rank = in_fo.xpath('span[3]/strong/text()')[0].strip()
else:
rank = in_fo.xpath('span[3]/text()')[0].strip()
song = in_fo.xpath('a/text()')[0].strip()
singer = in_fo.xpath('a/span/text()')[0].split('-')[1]
time = in_fo.xpath('span[4]/span/text()')[0].strip()
data = {
'rank': rank,
'singer': singer,
'song': song,
'time': time
}
return data
if __name__=='__main__':
# 获取网页列表
urls = ['https://www.kugou.com/yy/rank/home/{}-8888.html'.format(str(i)) for i in range(1, 24)]
# 遍历列表并进行爬取
for url in urls:
get_info_etree(url)