response = requests.get(url=url, headers=headers)
response.encoding = ‘gb2312’ # 设置编码方式
if response.status_code == 200: # 判断请求是否成功
html = etree.HTML(response.text) # 解析HTML
ip = html.xpath(‘//*[@id=“list”]/table/tbody/tr/td[1]/text()’) # 获取ip内容
port = html.xpath(‘//*[@id=“list”]/table/tbody/tr/td[2]/text()’) # 获取端口号
for j in range(0, 10):
my_ip = ip[j] + ‘:’ + port[j]
print(‘代理ip为:’, ip[j], ‘对应端口为:’, port[j])
ip_list.append(my_ip)
time.sleep(1)
ip_table[‘ip’] = ip_list # 将提取的ip保存至excel文件中的ip列
生成xlsx文件
ip_table.to_excel(‘E:/python/pythonProject3/venv/Include/ip.xlsx’, sheet_name=‘data’)
b. 读取ip并判断是否可用
这种方式存在的问题就是免费网站获取的ip有国内的有国外的,有可用的有不可用的,所以存在ip是失效的问题,解决办法就是掏钱买专门的api接口。
import time
import requests # 导入网络请求模块
import pandas # 导入pandas模块
from lxml import etree # 导入HTML解析模块
ip_table = pandas.read_excel(‘E:/python/pythonProject3/venv/Include/ip.xlsx’) # 读取代理IP文件内容
ip = ip_table[‘ip’] # 获取代理ip列信息
头部信息
headers = {‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36’,
‘Accept-Language’: ‘zh-CN,zh;q=0.9’}
循环遍历代理IP并通过代理发送网络请求
for i in ip:
proxies = {‘http’: ‘http://{}’.format(i),
‘https’: ‘https://{}’.format(i)}
try:
verify=False不验证服务器的SSL证书
response = requests.get(‘http://2021.ip138.com/’, headers=headers, proxies=proxies, verify=False, timeout=10)
if response.status_code == 200: # 判断请求是否成功,请求成功说明代理IP可用
response.encoding = ‘utf-8’ # 进行编码
html = etree.HTML(response.text) # 解析HTML
info_1 = str(html.xpath(‘/html/body/p[1]/text()[1]’)).replace(“['\n”, “”).replace(“[']”, “”)
info_2 = str(html.xpath(‘/html/body/p[1]/a/text()’)).replace(“['”, “”).replace(“']”, “”)
info_3 = str(html.xpath(‘/html/body/p[1]/text()[2]’)).replace(“[‘] “, “”).replace(”\n’]”, “”)
print(info_1 + info_2 + info_3) # 输出当前ip匿名信息
time.sleep(3)
except Exception as e:
pass
print(‘错误异常信息为:’, e) # 打印异常信息
c.通过专门的API接口获取ip
import requests # 导入网络请求模块
from lxml import etree # 导入HTML解析模块
import time
url = ‘api接口’
headers = {‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36’}
response = requests.get(url=url, headers=headers)
ip = str(response.text).replace(“\r”, “”).replace(“\n”, “”)
proxies = {‘http’: ‘http://{}’.format(ip),
‘https’: ‘https://{}’.format(ip)}
print(proxies)
try:
verify=False不验证服务器的SSL证书
response = requests.get(‘http://2021.ip138.com/’, headers=headers, proxies=proxies, verify=False, timeout=10)
if response.status_code == 200: # 判断请求是否成功,请求成功说明代理IP可用
response.encoding = ‘utf-8’ # 进行编码
html = etree.HTML(response.text) # 解析HTML
info_1 = str(html.xpath(‘/html/body/p[1]/text()[1]’)).replace(“['\n”, “”).replace(“[']”, “”)
info_2 = str(html.xpath(‘/html/body/p[1]/a/text()’)).replace(“['”, “”).replace(“']”, “”)
info_3 = str(html.xpath(‘/html/body/p[1]/text()[2]’)).replace(“[‘] “, “”).replace(”\n’]”, “”)
print(info_1 + info_2 + info_3) # 输出当前ip匿名信息
time.sleep(3)
except Exception as e:
pass
print(‘错误异常信息为:’, e) # 打印异常信息
==================================================================
当我们使用爬虫的时候大多数是为了爬取我们需要的部分数据,但直接获取到的往往不是我们需要的,这时候就需要我们对于爬取到的数据进行解析,进而在数据中找到我们需要的数据,接下来我将和大家一起使用正则(re)、Xpath、Beautiful Soup进行数据解析工作。
正则表达式顾名思义就是由字符组成的表达式,这些表达式根据不同的组合可以匹配字符串中需要的部分。
(1). 正则表达式基础
a. 行定位符
行定位符用于描述字符串的边界。
| 符号 | 作用 |
| — | — |
| ^ | 表示行的开始 |
| $ | 表示行的结尾 |
b.元字符
元字符使用:
\bmr\w*\b
\b表示单词的边界
mr表示匹配开头是mr的字串
\e*表示匹配任意数量的字母或数字
该表达式可以匹配mrsoft、mrsbook、mr1234等字符串
| 代码 | 说明 |
| — | — |
| . | 匹配除换行符以外的任意字符 |
| \w | 匹配字母、数字、下划线、汉字 |
| \W | 匹配除了字母、数字、下划线、汉字以外的字符(与\w相反) |
| \s | 匹配任意空白符 |
| \S | 匹配除单个空白符(包括Tab和换行符)以外所有字符 |
| \d | 匹配数字 |
| \D | 匹配任意非数字 |
| \A | 从字符串开始处匹配 |
| \Z | 从字符串结束处匹配 |
| \b | 匹配一个单词的边界,单词分界符通常是空格、标点或者换行 |
| \B | 匹配非单词边界 |
| ^ | 匹配字符串的开始 |
| $ | 匹配字符串的结束 |
| () | 被括起来的表达式将作为分组 |
c. 限定符
上面提到"\w*"可以匹配任意数量的字母或数字。如果我们要匹配一定数量的数字,比如11位数的手机号?这时候就可以用限定符来实现。
^\d{11}$
匹配11位数的电话号码
| 符号 | 说明 | 举例 |
| — | — | — |
| ? | 匹配前面的字符零次或一次 | colour?r 可以匹配到colour和color |
| + | 匹配前面的字符一次或多次 | go+gle 可以匹配gogle到goooo…gle |
| * | 匹配前面的字符零次或多次 | go*gle 可以匹配ggle到goooo…gle |
| {n} | 匹配前面的字符串n次 | go{2}gle 只可以匹配google |
| {n,} | 匹配前面的字符最少n次 | go{2,}gle 可以匹配从google到goooo…gle |
| {n,m} | 匹配前面的字符最少n次,最多m次 | employe{0,2} 可以匹配employ、employe\employee |
d.字符类
假如我们要匹配所有大小写字母和数字,你会怎么做?列举所有的可能?显然不是,这时候我们可以使用正则表达式提供的字符类,将我们的条件放在中括号里面,例如:
[a-z0-9A-Z] # 可以匹配所有字母和数字
e. 排除字符
上面我们可以利用字符类获取我们想要的字符,那如何排除我们不需要的字符呢,很简单,在上面的表达式前面加一个^就可以了,例如:
[^a-zA-Z] # 可以匹配一个不是字母的字符
f. 选择字符
如果我们要在一堆字符里面找出所有的手机号码或者是身份证号码,如何运用正则表达式呢?分析一下身份证号码的组成,一共18位,前17位位数字,最后一位为数字或者是X,根据这一描述,我们显然可以得出如下的表达式:
[^\d{18}KaTeX parse error: Undefined control sequence: \d at position 4: |(^\̲d̲{17}(\d|X|x))
g. 转义字符
正则表达式的转义字符和python的转义字符基本没什么区别,例如当我们需要匹配的是个ip地址时,192.168.1.1中的.如何匹配呢?前面我们说到正则里面的点可以匹配一个任意字符,那这里就需要对其进行转义.
[1-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3} # 匹配ip地址
h. python中的正则表达式
在python里面我们一般不会写模式字符串,即在转义的地方加上\,这样会导致表达式中有大量的\,取而代之的是原生表达式,在表达式前面加上 R 或 r.
(2). match() 匹配
match()从字符串的开始位置匹配,如果在起始位置匹配成功就直接返回结果,反之返回None.
re.match(‘正则表达式’, ‘待匹配字符串’, ‘修饰符’)
例如:
re.match(‘mr_\w+’, ‘MR_SHOPmr_shop’, re.I)
I 表示不区分大小写
| 表达式 | 匹配效果 | 匹配结果 |
| — | — | — |
| re.match(‘mr_\w+’, ‘MR_SHOPmr_shop’, re.I) | 匹配以指定字符串开头 | <re.Match object; span=(0, 7), match=‘MR_SHOP’> |
| re,match(“.ello”, “hello”) | 匹配任意开头的字符串 | <re.Match object; span=(0, 5), match=‘hello’> |
(3). search() 匹配
search()方法不同于match()方法,search()会在整个字符串搜索第一匹配的值,匹配成功就返回,否则返回None。
re,search(“mr_\w+”, “MR_SHOP”, re.I)
re,search(“mr_\w+”, “项目名称 MR_SHOP”, re.I)
两个表示匹配结果一样
| 表达式 | 匹配效果 |
| — | — |
| \d? | 匹配多个数字,可有可无 |
| \b | 表示字符串的边界,可以是开头、结尾、空格以及换行 |
(4). findall()匹配
findall()方法会搜索整个字符串寻找符合要求的字符,并以列表的形式返回,如果没有匹配到就会返回空列表。
| 表达式 | 匹配效果 |
| — | — |
| re.findall(‘mr_\w+’, ‘MR_SHOP mr_shop’, re.I) | 所有指定字符开头的字符串 |
| re.findall(‘https://(.*)/’, ‘http://www.hao123.com/’) | 贪婪匹配,获取//开始到/前面的所有字符 |
| re.findall(‘https://(.*?)/’, ‘http://www.hao123.com/’) | 非贪婪匹配,这样可能匹配不到任何字符,因为匹配结果会尽可能少 |
(5). 字符串处理
- 替换字符串
re.sub(‘正则表达式’, ‘要替换的字符串’, ‘要被替换的字符串’, ‘替换的最大次数,默认为0’, 修饰符)
import re
str = r’1[34578]\d{9}’
string = ‘中奖号码为3867363546 联系电话为:15071567345’
result = re.sub(str, ‘1**********’, string)
print(result)
输出结果为: 中奖号码为3867363546 联系电话为:1**********
- 分割字符串
re.split(‘正则表达式’, ‘要匹配的字符串’, 最大拆分次数, 修饰符)
import re
str = r’[?|&]’
url = ‘http://www.baidu.com?a=12&b=3’
result = re.split(str, url)
print(result)
输出结果为: [‘http://www.baidu.com’, ‘a=12’, ‘b=3’]
上一节我们学了正则表达式清洗数据,这一节我们学习一种更加便捷的数据清洗解析方式,XPath。这是一种基于XML的路径语言。
Xpath常用的路径表示:
| 表达式 | 描述 |
| — | — |
| nodename | 此节点的所有子节点 |
| / | 从当前节点选取子节点 |
| // | 从当前节点选取子孙节点 |
| . | 选取当前节点 |
| … | 选取当前节点的父节点 |
| @ | 选取属性class |
| * | 选取所有节点 |
这种解析方式主要熟悉网页结构,利用上面的路径表达式选取对应的路径。浏览器也提供了直接复制的Xpath路径,使用如下:
这里我就不再详细介绍这种解析方法,大家可以参考这位博主的文章,写的很详细了!Xpath解析数据
from lxml import etree
import requests
url = “https://wuhan.zbj.com/search/f/?type=new&kw=%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%BC%80%E5%8F%91”
resp = requests.get(url)
xml = resp.text
tree = etree.HTML(xml)
res = tree.xpath(‘//div[@class=“service-info-wrap”]’)
print(res)
for item in res:
price = item.xpath(‘./div[@class=“service-price clearfix”]/span/text()’)
title = item.xpath(‘./div[@class=“service-title”]/p/text()’)
result = {
“price”: ‘’.join(price),
“title”: ‘’.join(title)
}
print(result)
BeautifulSoup是一个用于从HTML和XML中提取数据的Python库。
(1). BeautifulSoup的简单应用
使用第一步先导入bs4库,然后创建一个BeautifulSoup对象指定选用的解析器。
from bs4 import BeautifulSoup # 导入BeautifulSoup库
创建模拟HTML代码的字符串
html_doc = “”"
body 元素的内容会显示在浏览器中。
title 元素的内容会显示在浏览器的标题栏中。
“”"
创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features=“lxml”)
print(soup) # 打印解析的HTML代码
print(type(soup)) # 打印数据类型
这样我们就完成了数据的第一步处理工作
(2). 获取节点内容
下面以一个例子加代码注释解释如何获取节点内容。
- 获取节点源代码
from bs4 import BeautifulSoup # 导入BeautifulSoup库
创建模拟HTML代码的字符串
html_doc = “”"
body 元素的内容会显示在浏览器中。
title 元素的内容会显示在浏览器的标题栏中。
“”"
创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features=“lxml”)
“”"
获取节点内容
“”"
print(‘head节点内容为:\n’, soup.head) # 打印head节点
- 获取节点属性
在已选择的节点后面加上.attrs即可
创建模拟HTML代码的字符串
html_doc = “”"
“”"
创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features=“lxml”)
print(‘meta节点中属性如下:\n’,soup.meta.attrs)
print(‘link节点中属性如下:\n’,soup.link.attrs)
- 获取节点的文本内容
在已获取的节点后面加上.string即可。
from bs4 import BeautifulSoup # 导入BeautifulSoup库
创建模拟HTML代码的字符串
html_doc = “”"
“”"
创建一个BeautifulSoup对象,获取页面正文
soup = BeautifulSoup(html_doc, features=“lxml”)
print(‘titlt节点中的文本如为:’, soup.title.string)
(3). 方法获取内容
- find_all()方法——获取所有符合条件的节点
find_all(name=None, attrs={}, recursive=True, text=None, limit=None, **kwaigs)
- find_all(name)
通过节点名称获取内容。
soup.find_all(name=‘标签名’)
- find_all(attrs)
通过指定属性获取内容
soup.find_all(class=‘newslist’)
- fina_all(tetx)
获取指定文本内容。
soup.find_all(text=‘文本内容’)
- find()——获取第一个匹配的节点
find()的各项参数和find_all一样,不同的是前者可以匹配所有符合匹配条件的字符,后者只能匹配第一个符合条件的字符
**tip:**还有很多其他不常用的方法,自行查阅了解。
(4). CSS选择器
- 通过标签查找
print soup.select(‘title’) # 查找title标签
- 通过类名查找
print soup.select(‘.sister’) # 通过class类名查找
- 通过id名查找
print soup.select(‘#link1’) # 通过id="link2"查找
- 组合查找
print soup.select(‘p #link1’)
查找p标签下id="link1"的内容
print soup.select(“head > title”)
查找head标签下的title标签的内容
- 属性查找
print soup.select(‘a[class=“sister”]’)
查找a便签而且class="sister"的内容
====================================================================
目标:爬取豆瓣电影top250的相关信息
第二页url: https://movie.douban.com/top250?start=25&filter=
第三页url: https://movie.douban.com/top250?start=50&filter=
正则表达式:
import re # 导入re模块
import time # 导入时间模块
import random # 导入随机模块
import requests # 导入网络请求模块
header = {‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36’}
处理字符串中的空白符,并拼接字符串
def processing(strs):
s = ‘’ # 定义保存内容的字符串
for n in strs:
n = ‘’.join(n.split()) # 去除空字符
n = n.replace(" ", “”)
s = s + n # 拼接字符串
return s # 返回拼接后的字符串
获取电影信息
def get_movie_info(url):
response = requests.get(url, headers=header) # 发送网络请求
result = response.text
li_all = re.findall(r’
- [\s\S]*?
- ', result)
print(li_all[0])
for item in li_all:
names = re.findall(r’(.*)', item) # 获取电影名字相关信息
name = processing(names) # 处理电影名称信息
infos = re.findall(r’导演:(.*?)
', item) # 获取导演、主演等信息info = processing(infos) # 处理导演、主演等信息
scores = re.findall(r’
', item) # 获取电影评分score = processing(scores)
evaluations = re.findall(r’(.*)', item) # 获取评分人数
evaluation = processing(evaluations)
summarys = re.findall(r’(.*)', item) # 获取评分人数
summary = processing(summarys)
print(‘电影名称:’, name)
print(‘导演与演员:’, info)
print(‘电影评分:’, score)
print(‘评价人数:’, evaluation)
print(‘电影总结:’, summary)
print(‘--------分隔线--------’)
if name == ‘main’:
for i in range(0, 25, 25): # 每页25为间隔,实现循环,只爬取前5页
通过format替换切换页码的url地址
url = ‘https://movie.douban.com/top250?start={page}&filter=’.format(page=i)
get_movie_info(url) # 调用爬虫方法,获取电影信息
time.sleep(random.randint(1, 3)) # 等待1至3秒随机时间
Xpath:
from lxml import etree # 导入etree子模块
import time # 导入时间模块
import random # 导入随机模块
import requests # 导入网络请求模块
header = {‘User-Agent’: ‘Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36’}
处理字符串中的空白符,并拼接字符串
def processing(strs):
s = ‘’ # 定义保存内容的字符串
for n in strs:
n = ‘’.join(n.split()) # 去除空字符
s = s + n # 拼接字符串
return s # 返回拼接后的字符串
获取电影信息
def get_movie_info(url):
response = requests.get(url, headers=header) # 发送网络请求
html = etree.HTML(response.text) # 解析html字符串
div_all = html.xpath(‘//div[@class=“info”]’)
for div in div_all:
names = div.xpath(‘./div[@class=“hd”]/a//span/text()’) # 获取电影名字相关信息
name = processing(names) # 处理电影名称信息
infos = div.xpath(‘./div[@class=“bd”]/p/text()’) # 获取导演、主演等信息
info = processing(infos) # 处理导演、主演等信息
score = div.xpath(‘./div[@class=“bd”]/div/span[2]/text()’) # 获取电影评分
evaluation = div.xpath(‘./div[@class=“bd”]/div/span[4]/text()’) # 获取评价人数
获取电影总结文字
summary = div.xpath(‘./div[@class=“bd”]/p[@class=“quote”]/span/text()’)
print(‘电影名称:’, name)
print(‘导演与演员:’, info)
print(‘电影评分:’, score)
print(‘评价人数:’, evaluation)
print(‘电影总结:’, summary)
print(‘--------分隔线--------’)
if name == ‘main’:
for i in range(0, 125, 25): # 每页25为间隔,实现循环,只爬取前5页
通过format替换切换页码的url地址
url = ‘https://movie.douban.com/top250?start={page}&filter=’.format(page=i)
get_movie_info(url) # 调用爬虫方法,获取电影信息
time.sleep(random.randint(1, 3)) # 等待1至3秒随机时间
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)
re)
print(‘评价人数:’, evaluation)
print(‘电影总结:’, summary)
print(‘--------分隔线--------’)
if name == ‘main’:
for i in range(0, 125, 25): # 每页25为间隔,实现循环,只爬取前5页
通过format替换切换页码的url地址
url = ‘https://movie.douban.com/top250?start={page}&filter=’.format(page=i)
get_movie_info(url) # 调用爬虫方法,获取电影信息
time.sleep(random.randint(1, 3)) # 等待1至3秒随机时间
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Python工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Python开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
[外链图片转存中…(img-6GFKcCck-1712755619349)]
[外链图片转存中…(img-VvmNX0sH-1712755619350)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以扫码获取!!!(备注Python)