""""
反爬机制:门户网站,可以通过制定相应的策略或者技术手段,防止爬虫程序进行网站数据的爬取。
反反爬策略:爬虫程序可以通过制定相关的策略或者技术手段,破解门户网站中具备的反爬机制,从而可以获取门户网站中相关的数据。
robots.txt协议:君子协议。规定了网站中哪些数据可以被爬虫爬取哪些数据不可以被爬取。
"""
from urllib.request import urlopen # 来自 网页模块.请求 导入 网页打开
url = "http://www.baidu.com"
resp = urlopen(url)
print(resp) # <http.client.HTTPResponse object at 0x000002814508BFD0>
print(resp.read()) # 此时拿到的是页面源代码 (b' 二进制)
print(resp.read().decode("utf-8")) # 此时拿到的是页面源代码 (UTF-8模式)
# ctrl+f 搜索:charset ,确定转化成 utf-8 , GBK 搜索结果:charset=utf-8
# 源代码:html , css ,js
with open("mybaid.html", mode="w", encoding="utf-8") as f: # 创建文件.html格式 写 UTF-8模式
f.write(resp.read().decode("utf-8")) # 写的内容:读取resp 以UTF-8模式写入
# 细节:打开写入的文件 "mybaidu.html",以浏览器或者别的方式打开,你就能看到网站模式。
# 如果直接print,只能看到源代码。必须写出来才行~
# 你可以下写入的网站上进行修改,都可以。哈哈~~恶作剧啥的
//***** requests 测试
import requests
# 爬取百度的页面源代码
url = "http://www.baidu.com"
resp = requests.get(url)
resp.encoding = "utf-8"
print(resp) # <Response [200]>
print(resp.text) # 拿到页面源代码
//**************** get 请求
import requests
content = input('请输入你要检索的内容:')
url = f"https://www.sogou.com/web?query={content}"
headers = {
# 添加一个请求头信息. UA
"User-Agent": " Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
}
# 处理一个小小的反爬 细节:这是字典
resp = requests.get(url, headers=headers)
print(resp.text)
print(resp.request.headers) # 可以查看到请求头信息
# {'User-Agent': 'Mozilla/5.0 xxxx', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive'}
# 你会发现,就是我们写入的请求头
//******
# 如果不写:headers 的话,默认的 python 的 requests 的请求头信息是什么呢?
resp = requests.get(url)
print(resp.request.headers) # python-requests/2.31.0 这时默认的。所以,服务器会识别出来。
# {'User-Agent': 'python-requests/2.31.0', ......}
# {'User-Agent': 'python-requests/2.31.0', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Cookie': 'ABTEST=0|1703085357|v17; SNUID=658039558B8C8778FE4F23738BB63A7E; IPLOC=CN5000; SUID=EF0AB2DE2431A40A000000006583052D; cuid=AAHKKmo+SQAAAAqgKmxzkgAAEAM='}
//********************* post 请求
import requests
import json
url = "https://fanyi.baidu.com/sug"
hehe = {
"kw": input("请输入一个单词")
}
resp = requests.post(url, data=hehe)
print(resp.text) # 拿到的是文本字符串
# {"errno":0,"data":[{"k":"Apple","v":"n. \u82f9\u679c\u516c\u53f8\uff0c\u539f\u79f0\u82f9\u679c\u7535\u8111\u516c\u53f8"},{"k":"apple","v":"n. \u82f9\u679c; \u82f9\u679c\u516c\u53f8; \u82f9\u679c\u6811"},{"k":"APPLE","v":"n. \u82f9\u679c"},{"k":"apples","v":"n. \u82f9\u679c\uff0c\u82f9\u679c\u6811( apple\u7684\u540d\u8bcd\u590d\u6570 ); .....}
print(resp.json()) # 此时拿到的直接是json数据 (字典)
# {'errno': 0, 'data': [{'k': 'Apple', 'v': 'n. 苹果公司,原称苹果电脑公司'}, {'k': 'apple', 'v': 'n. 苹果; 苹果公司; 苹果树'}, {'k': 'APPLE', 'v': 'n. 苹果'}, {'k': 'apples', 'v': 'n. 苹果,苹果树( apple的名词复数 ); [美国口语]棒球; [美国英语][保龄球]坏球; '}, {'k': 'Apples', 'v': '[地名] [瑞士] 阿
print(resp.json()['data']) # 拿到的就是'data' 的value
//***********************
import requests
url = "https://movie.douban.com/j/chart/top_list"
hehe = "type=13&interval_id=100%3A90&action=&start=0&limit=20"
resp = requests.get(url,hehe) # 处理一个小小的反爬
print(resp.text) # 会发现,什么都没有!! 那就是:检测设备。那就反爬
"""""
说明一下 parse
hehe = {
"type": "13",
"interval_id": "100:90",
"action": "",
"start": "0",
"limit": "20"
}
params=hehe 等价于 hehe = "type=13&interval_id=100%3A90&action=&start=0&limit=20"
# 你可理解成: parse 相当于 把字典拼(:)接成(=)形式
所以,我们就写成字典方式
"""""
import requests
url = "https://movie.douban.com/j/chart/top_list"
hehe = {
"type": "13",
"interval_id": "100:90",
"action": "",
"start": "0",
"limit": "20"
}
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"
}
resp = requests.get(url, params=hehe, headers=headers) # 处理一个小小的反爬 你看这下面:\/view\/photo\/s_ratio_poster\ 明显有问题。把网站换个样式了
print(resp.text) # [{"rating":["9.6","50"],"rank":1,"cover_url":"https://img1.doubanio.com\/view\/photo\/s_ratio_poster\/public\/p2561716440.jpg" .....
print(resp.json()) # [{'rating': ['9.6', '50'], 'rank': 1, 'cover_url': 'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2561716440.jpg', ...
# 通过 json()就把网址正确输出了 以后json()也用一下吧,觉得。
print(resp.request.url) # https://movie.douban.com/j/chart/top_list?type=13&interval_id=100%3A90&action=&start=0&limit=20
print(resp.request) # <PreparedRequest [GET]>
# 细节: 请求的时候requests会自动拼接带'?' 不用写成 (url, '?',params=hehe) 这种形式
//************* 正则表达式
import re
result = re.findall("a", "我是一个abcdeafg")
print(result) # ['a', 'a']
result = re.findall(r"\d+", "我今年18岁, 我有200000000块")
print(result) # ['18', '200000000']
# 这个是重点. 多多练习 效率高
result = re.finditer(r"\d+", "我今年18岁, 我有200000000块")
print(result) # <callable_iterator object at 0x000001E02B3BAA70>
for item in result: # 从迭代器中拿到内容
print(item) # <re.Match object; span=(3, 5), match='18'> ** <re.Match object; span=(10, 19), match='200000000'>
print(item.group()) # 18 从匹配到的结果中拿到数据 ** 200000000
# search只会匹配到第一次匹配的内容
result = re.search(r"\d+", "我叫周杰伦, 今年32岁, 我的班级是5年4班")
print(result) # <re.Match object; span=(9, 11), match='32'>
print(result.group()) # 32
# match, 在匹配的时候. 是从字符串的开头进行匹配的, 类似在正则前面加上了^\d
result = re.match(r"\d+", "666叫88周杰伦, 今年32岁, 我的班级是5年4班")
print(result) # <re.Match object; span=(0, 3), match='666'>
print(result.group()) # 666 必须是开头开始
result = re.match(r"\d+", "叫88周杰伦, 今年32岁, 我的班级是5年4班")
print(result) # None
print(result.group()) # 报错的!!!
# 预加载, 提前把正则对象加载完毕
obj = re.compile(r"\d+")
# 直接把加载好的正则进行使用
result = obj.findall("我叫周杰伦, 今年32岁, 我的班级是5年4班") #分开加载:re 和 数据
print(result) # ['32', '5', '4']
# 想要提取数据必须用小括号括起来. 可以单独起名字
# (?P<名字>正则)
# 提取数据的时候. 需要group("名字")
s = """
<div class='西游记'><span id='10010'>中国联通</span></div>
<div class='西游记'><span id='10086'>中国移动</span></div>
"""
obj = re.compile(r"<span id='\d+'>.*?</span>")
result = obj.findall(s) # ["<span id='10010'>中国联通</span>", "<span id='10086'>中国移动</span>"]
obj = re.compile(r"<span id='(\d+)'>(.*?)</span>")
result = obj.findall(s) # [('10010', '中国联通'), ('10086', '中国移动')]
obj = re.compile(r"<span id='(?P<id>.*?)'>(?P<name>.*?)</span>")
result = obj.finditer(s)
print(result) # obj = re.compile(r"<span id='(?P<id>\d+)'>(?P<name>.*?)</span>") 迭代器
for item in result:
id = item.group("id") # 必须是 "id" 或者 "name"
print(id) # 10010 ** 10086
name = item.group("name")
print(name) # 中国联通 ** 中国移动
//***************************** 豆瓣
import requests
import re
f = open("豆瓣250电影.csv", mode="w", encoding='utf-8')
url = "https://movie.douban.com/top250?start=200&filter="
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"
}
resp = requests.get(url) # <Response [418]> 反爬机制 headers 解决
resp = requests.get(url, headers=headers)
# resp.encoding = 'utf-8' # 解决乱码问题.
pageSource = resp.text
# 编写正则表达式 r'xxxxxx' 用单引号,避免跟""冲突
# re.S 可以让正则中的.匹配换行符 (让.也涵盖换行) 指定re规则
obj = re.compile(r'<div class="item">.*?<span class="title">(?P<name>.*?)</sp'
r'an>.*?导演: (?P<dao>.*?) .*?<br>'
r'(?P<year>.*?) .*?<span class="rating_num" property="v:average">'
r'(?P<score>.*?)</span>.*?<span>(?P<num>.*?)人评价</span>', re.S)
# 进行正则匹配 通过这个制定的re规则,来处理 resp.text数据
result = obj.finditer(pageSource)
for item in result:
name = item.group("name")
dao = item.group("dao")
year = item.group("year").strip() # 去掉字符串左右两端的空白 空格----1949,位置在最前面。随意会有空格。输出的时候屏蔽掉
score = item.group("score")
num = item.group("num")
f.write(f"{name},{dao},{year},{score},{num}\n") # 如果觉着low. 可以更换成csv模块. 进行数据写入
f.close()
resp.close()
print("豆瓣TOP250提取完毕.")
//***************** 自己写的 取了特有部分,+1+1+1
import re
import requests
url = "https://movie.douban.com/top250?start=0&filter="
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
}
resp = requests.get(url,headers=headers)
resp.encoding="utf-8"
# print(resp.text)
w=1
while w <25:
p=str(w)
obj=re.compile(r'<em class="">'+p+'</em>.*?<span class="title">(?P<name>.*?)</span>.*?导演: '
r'(?P<daoyan>.*?); .*?v:average">(?P<score>.*?)</span>.*?<span>(?P<num>.*?</span>)',re.S)
result=obj.finditer(resp.text)
for item in result:
name=item.group("name")
score=item.group("score")
daoyan=item.group("daoyan")
num=item.group("num")
print(name,daoyan,score,num)
w=w+1
//************************** 循环列表
# 如何翻页提取?
# (页数 - 1)*25 => start
import requests
import re
f = open("豆瓣250电影.csv", mode="w", encoding='utf-8')
i=-25
while i<250:
url = "https://movie.douban.com/top250?start="+str(i+25)+"&filter="
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"
}
resp = requests.get(url)
resp = requests.get(url, headers=headers)
pageSource = resp.text
obj = re.compile(r'<div class="item">.*?<span class="title">(?P<name>.*?)</sp'
r'an>.*?导演: (?P<dao>.*?) .*?<br>'
r'(?P<year>.*?) .*?<span class="rating_num" property="v:average">'
r'(?P<score>.*?)</span>.*?<span>(?P<num>.*?)人评价</span>', re.S)
# 进行正则匹配
result = obj.finditer(pageSource)
for item in result:
name = item.group("name")
dao = item.group("dao")
year = item.group("year").strip() # 去掉字符串左右两端的空白 空格----1949,位置在最前面。随意会有空格。输出的时候屏蔽掉
score = item.group("score")
num = item.group("num")
f.write(f"{name},{dao},{year},{score},{num}\n") # 如果觉着low. 可以更换成csv模块. 进行数据写入
i=i+25 #细节:这个不在for循环里
f.close() # 退出 while 循环,才关闭!!
resp.close() # 退出 while 循环,才关闭!!
print("豆瓣TOP250提取10页数据完毕.")
//********** 获取电影天堂 电影信息
"""""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="https://blog.csdn.net/rassamqi?spm=1011.2124.3001.5343">麦合学长</a>
</body>
</html>
""""" # <a> ------- </a> 这是一个结构 <a href="xxxx"> 麦合学长 </a> 页面:出现字,点击就是xxxx连接
"""
1. 提取到主页面中的每一个电影的背后的那个url地址
1. 拿到 "2021必看热片" 那一块的HTML代码.
2. 从刚才拿到的HTML代码中提取到href的值
2. 访问子页面, 提取到电影的名称以及下载地址
1. 拿到子页面的页面源代码
2. 数据提取
"""
import requests
import re
f = open("电影天堂.csv", mode="w", encoding='utf-8')
url = "https://www.dy2018.com/"
resp = requests.get(url)
resp.encoding = "gbk" # 源代码 charset 是GBK (国内网站,不是GBK,就是UTF-8)
# print(resp.text) 判断一下有没有正常输出
# 1.提取2021必看热片部分的HTML代码
obj1 = re.compile(r"2023必看热片.*?<ul>(?P<html>.*?)</ul>", re.S)
result1 = obj1.search(resp.text)
html = result1.group("html")
# 2.提取a标签中的href的值
obj2 = re.compile(r"<li><a href='(?P<href>.*?)' title")
result2 = obj2.finditer(html) # 细节:从html里面进行进一步判断
# 细节:截取信息,可以从 id class 等入手
obj3 = re.compile(r'<div id="Zoom">.*?◎片 名(?P<movie>.*?)<br />.*?<td style="WORD-WRAP: break-word"'
r' bgcolor="#fdfddf"><a href="(?P<download>.*?)">', re.S) # 正则工具准备好
for item in result2:
# print(item.group("href")) 肯定不行,必须拼接
# 拼接出子页面的url
child_url = url.strip("/") + item.group("href") # 细节:别忘了删掉后面的"/" 。因为多余了
child_resp = requests.get(child_url)
child_resp.encoding = 'gbk'
result3 = obj3.search(child_resp.text) # 用obj3工具,对数据text进行修改 一个html只有一个数据,所以可以用 search
movie = result3.group("movie")
download = result3.group("download")
print(movie, download)
f.write(f"{movie},{download}\n")
f.close() # 退出 while 循环,才关闭!!
resp.close() # 退出 while 循环,才关闭!!
print("电影天堂数据爬取完毕.")
//******* 细节补充
# 爬虫过程中,突然出现,无法爬取。刚开始的 print(resp.text) 就不行
# 原因:因为,该网站偶尔检测到这时非浏览器行为,检测到了设备
# 两种办法:1.加请求头 headers
# 2.过一会儿再试一试,会好的
# 如果爬虫量大----> 会导致网站挂掉。可能网站会拉黑你的ip。所以,不要爬虫太狠~~
//************** 自己写的
import re
import requests
url="https://www.1905.com/vod/?id=1"
headers={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
}
resp=requests.get(url,headers=headers)
resp.encoding="utf-8"
# print(resp.text)
obj1=re.compile(r'title="欧美">欧美</a>(?P<html>.*?)title="内地">',re.S)
rusult=obj1.search(resp.text)
html=rusult.group("html")
# print(html)
obj2=re.compile(r'<a href="(?P<name>.*?)" target="')
obj3=re.compile(r'<span id="playerBoxIntroCon">(?P<xinxi>.*?)<a href=')
# 第二部,在网站内部,获取电影的信息
headers1={
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"
}
result2=obj2.finditer(html)
for item in result2:
# print(item.group("name"))
resp2=requests.get(item.group("name"))
resp.encoding="utf-8"
# print(resp2)
result3=resp.text
result4=obj3.search(result3)
try:
xinxi=result4.group("xinxi")
print(xinxi)
except AttributeError as e:
print(e)
pass
# 程序没问题!!
//********************** html 简单入门
"""""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>我是标题</title>
</head>
<body bgcolor="pink">
<h1 align="right">我爱周润发</h1>
<p>周润发同志. 曾经是一个赌神. 我特别崇拜他</p>
<a href="http://www.baidu.com">周润发的个人主页</a>
<img src="abc.jpg" width="50px" height="60px"/>
</body>
</html>
<!--
html基本语法:
1. <标签名 属性="值">被标记的内容</标签名>
2. <标签名 属性="值" />
-->
"""""
"""""
//**************** ChildProcessError<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="mycss.css">
<style>
span{
color: pink;
}
</style>
</head>
<body>
<div style="width:100px;height:100px;border: 1px solid red;">你好, 我叫周润发</div>
<span>我爱黎明</span>
</body>
</html>
"""""
# //****** CSS 选择器 自己去源代码看吧。我弄过来,好多乱码
//************* bs4
# 安装bs4
# pip install bs4
from bs4 import BeautifulSoup
html = """
<ul>
<li><a href="zhangwuji.com">张无忌</a></li>
<li id="abc"><a href="zhouxingchi.com">周星驰</a></li>
<li><a href="zhubajie.com">猪八戒</a></li>
<li><a href="wuzetian.com">武则天</a></li>
<a href="jinmaoshiwang.com">金毛狮王</a> # 这个就拿不到了
</ul>
"""
# 1. 初始化BeautifulSoup对象
page = BeautifulSoup(html, "html.parser") # 解析(parser)
# page.find("标签名", attrs={"属性": "值"}) # 查找某个元素, 只会找到一个结果
# page.find_all("标签名", attrs={"属性": "值"}) # 找到所有结果
li = page.find("li", attrs={"id":"abc"})
print(li) # <li id="abc"><a href="zhouxingchi.com">周星驰</a></li>
# li 标签里面,还有 a 标签
a = li.find("a") # 只有一个标签,不用属性都可以
print(a.text) # 拿文本 周星驰
print(a.get("href")) # 拿属性. get("属性名") zhouxingchi.com
li_list = page.find_all("li") # 所有 li 标签
for li in li_list:
a = li.find("a")
text = a.text # 张无忌
href = a.get("href") # zhangwuji.com
print(text, href) # 张无忌 zhangwuji.com
# 周星驰 zhouxingchi.com
# 猪八戒 zhubajie.com
# 武则天 wuzetian.com
//************** bs4 实战 北京新发地 自己写的
import requests
f=open("北京新发地价格表.text",mode="w",encoding="utf-8")
url = 'http://www.xinfadi.com.cn/getPriceData.html'
t=1
while t<30:
body = {
'limit': 20,
'current':t # 页数
}
res = requests.post(url, data=body)
r=res.json()["list"]
# print(res.json()["list"])
# print(res.text)
for item in r:
id=item["id"]
prodName= item["prodName"]
lowPrice = item["lowPrice"]
highPrice = item["highPrice"]
avgPrice = item["avgPrice"]
place = item["place"]
pubDate = item["pubDate"]
# print(id,prodName,lowPrice,highPrice,avgPrice,place,pubDate)
f.write(f"编号:{id},产品名:{prodName},最低价{lowPrice},最高价{highPrice},平均价{avgPrice},产地{place},产出时间{pubDate}\n")
# f.write(id,prodName,lowPrice,highPrice,avgPrice,place,pubDate)
print("正在爬虫.....")
t=t+1
print("爬虫结束")
//****************** 老师的代码 北京新发地
import requests
from bs4 import BeautifulSoup
f = open("新发地菜价.csv", mode="w", encoding='utf-8')
url = "http://www.xinfadi.com.cn/marketanalysis/0/list/1.shtml"
resp = requests.get(url)
# 初始化BS4对象
page = BeautifulSoup(resp.text, "html.parser")
table = page.find("table", attrs={"class": "hq_table"}) # 细节:我只要找到一个地方就行
trs = table.find_all("tr")[1:] # 此时拿到除了第一行外的所有tr 标签 具体情况,具体分析
for tr in trs: # 每一行
tds = tr.find_all("td") # 在找到 tr 里面的 td 标签
name = tds[0].text # 找到文本内容
low = tds[1].text
avg = tds[2].text
hig = tds[3].text
kind = tds[4].text
dan = tds[5].text
date = tds[6].text
# print(name, low, avg, hig, kind, dan, date)
f.write(f"{name},{low},{avg},{hig},{kind},{dan},{date}\n") # 太好用了这方法
f.close()
resp.close()
print("爬取成功")
# 核心:处理tr td 模式 <tr class=.... <td 属性 >值1/文本1</td><td 属性 >值2/文本2</td>....></tr>
# 实际上:<tr class=.... <td 属性 >值1/文本1</td><td 属性 >值2/文本2</td>....></tr><tr class=.... <td 属性 >值1/文本1</td><td 属性 >值2/文本2</td>....></tr>
# 就这样连着的 tr 行 / td 列
//************** 哈哈哈 12.23 半夜不睡觉,下载美女图片哈哈
import requests
from bs4 import BeautifulSoup
import re
url = "https://www.umei.net"
# doman = "https://www.umei.net/bizhitupian/xiaoqingxinbizhi/"
resp = requests.get(url)
resp.encoding = "utf-8"
n = 1 # 图片名称
obj=re.compile(r'<li class="i_list list_n2"> <a href="(?P<ur>.*?)" title=')
result=obj.finditer(resp.text)
obj3=re.compile(r'<!-- 正文图片显示 -->(?P<aa>.*?)<div',re.S)
obj4=re.compile(r'src="(?P<qq>.*?)">')
for item in result:
# print(item.group("ur"))
main_page = BeautifulSoup(resp.text, "html.parser")
child_url = url+item.group("ur")
child_resp = requests.get(child_url) # 请求到子页面
child_resp.encoding = "utf-8"
r = obj3.search(child_resp.text)
p=r.group("aa")
w=obj4.search(p)
y=w.group("qq")
img_resp = requests.get(y)
# print(img_resp.text) # 注意, 图片不是文本. 不能获取text的内容
with open(f"性感美女图片{n}.jpg", mode="wb") as f: # 注意, 此时写入到文件的是字节. 所以必须是wb
f.write(img_resp.content) # 把图片信息写入到文件中
print(f"{n}图片下载完毕")
n += 1
if n==6:
break
print("美女图片下载完毕")
# 老师演示的时候,是去年的课程,还有点绿色。我现在打开,贼黄。忍不住下载了几张~哈哈
//*** 补充
import requests
from bs4 import BeautifulSoup
import re
k=' <p><a href="/tupian/68362_2.html" title="下一页><img src="https://oss-img.ojbkcdn.com/tutuji/20231018/xcp5ycmweti.jpg"></a></p>'
child_bs = BeautifulSoup(k, "html.parser")
div = child_bs.find("p")
di=div.find("a")
d=di.find("img").get("src")
print(d) # https://oss-img.ojbkcdn.com/tutuji/20231018/xcp5ycmweti.jpg
//**************** 图片 老师代码
import requests
from bs4 import BeautifulSoup
domain = "https://www.umei.net"
"""
注意,
子页面的url如果开头是/, 直接在前面拼接上域名即可
子页面的url不是/开头, 此时需要找到主页面的url, 去掉最后一个/后面的所有内容. 和当前获取到的url进行拼接
"""
url = "https://www.umei.net/bizhitupian/xiaoqingxinbizhi/"
resp = requests.get(url)
resp.encoding = "utf-8"
n = 1 # 图片名称
main_page = BeautifulSoup(resp.text, "html.parser")
a_list = main_page.find_all("a", attrs={"class": "TypeBigPics"})
for a in a_list:
href = a.get("href")
child_url = domain + href
child_resp = requests.get(child_url) # 请求到子页面
child_resp.encoding = "utf-8"
# 子页面的bs对象
child_bs = BeautifulSoup(child_resp.text, "html.parser")
div = child_bs.find("div", attrs={"class": "ImageBody"})
img_src = div.find("img").get("src") # 拿到图片的下载路径
# print(img_src)
# 下载图片
img_resp = requests.get(img_src)
# print(img_resp.text) # 注意, 图片不是文本. 不能获取text的内容
with open(f"图片{n}.jpg", mode="wb") as f: # 注意, 此时写入到文件的是字节. 所以必须是wb
f.write(img_resp.content) # 把图片信息写入到文件中
print(f"{n}图片下载完毕")
n += 1
//********* xpath 入门
from lxml import etree
# 如果pycharm报错. 可以考虑这种导入方式
# from lxml import html
# etree = html.etree
xml = """
<book>
<id>1</id>
<name>野花遍地香</name>
<name>hahaha </name>
<price>1.23</price>
<nick>臭豆腐</nick>
<author>
<nick id="10086">周大强</nick>
<nick id="10010">周芷若</nick>
<nick class="jay">周杰伦</nick>
<nick class="jolin">蔡依林</nick>
<div>
<nick>惹了</nick>
</div>
</author>
<partner>
<nick id="ppc">胖胖陈</nick>
<nick id="ppbc">胖胖不陈</nick>
</partner>
</book>
"""
# 此时练习只能用XMLxml
et = etree.XML(xml)
result = et.xpath("/book") # / 表示根节点
result = et.xpath("/book/name") # 在xpath中间的/表示的是儿子
result = et.xpath("/book/name/text()")[0] # text() 拿文本
result = et.xpath("/book//nick") # //表示的是子孙后代.
result = et.xpath("/book/*/nick/text()") # * 通配符. 谁都行
result = et.xpath("/book/author/nick[@class='jay']/text()") # []表示属性筛选. @属性名=值 find(Nick, attrs={"class":"jay"})
result = et.xpath("/book/partner/nick/@id") # 最后一个/表示拿到nick里面的id的内容, @属性. 可以直接拿到属性值
print(result)
# xpath处理HTML
html = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
</head>
<body>
<ul>
<li><a href="http://www.baidu.com">百度</a></li>
<li><a href="http://www.google.com">谷歌</a></li>
<li><a href="http://www.sogou.com">搜狗</a></li>
</ul>
<ol>
<li><a href="feiji">飞机</a></li>
<li><a href="dapao">大炮</a></li>
<li><a href="huoche">火车</a></li>
</ol>
<div class="job">李嘉诚</div>
<div class="common">胡辣汤</div>
</body>
</html>
"""
et = etree.HTML(html)
li_list = et.xpath("/html/body/ul/li[2]/a/text()")
print(li_list)
li_list = et.xpath("//li")
for li in li_list:
href = li.xpath("./a/@href")[0] # ./表示当前节点
text = li.xpath("./a/text()")[0] # ./表示当前节点
print(text, href)
# 后续的爬虫工作.....
//******************* 自己写的 没问题 58
"""
1. 拿到页面源代码
2. 从页面源代码中提取你需要的数据. 价格, 名称, 公司名称
"""
import re
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/109.0.0.0 Safari/537.36"
}
url = "https://cq.58.com/ershouche/?utm_source=market&spm=u-2d2yxv86y3v43nkddh1.BDPCPZ_BT&PGTID=0d100000-0002-51f0-df9c-b9edf18814ef&ClickID=5"
resp = requests.get(url)
resp.encoding = "utf-8"
# print(resp.text)
# 提取数据
et = etree.HTML(resp.text)
print(5)
q=et.xpath("//ul[@class='infos infos-card h-clearfix']/li")
obj1=re.compile(r" (?P<ee>.*?)\n")
for item in q:
wan=item.xpath("./div/a/div/span/text()")
date=item.xpath("./div/a/p/text()")
if not date: # 过滤掉无用的数据
continue
if not wan: # 过滤掉无用的数据
continue
t=item.xpath("./div/a/div[2]/h2/span/font/text()")
w=item.xpath("./div/a/div[2]/h2/span/text()")
o=item.xpath("./div/a/div[2]/div[2]/text()")
p=obj1.search(w[0])
u=p.group("ee")
# print(date[0],t[0],u)
# print(u)
print(t,o,w,u,date,wan)
//********** 老师演示
"""
1. 拿到页面源代码
2. 从页面源代码中提取你需要的数据. 价格, 名称, 公司名称
"""
import requests
from lxml import etree
url = "https://beijing.zbj.com/search/f/?type=new&kw=saas"
resp = requests.get(url)
resp.encoding = "utf-8"
# print(resp.text)
# 提取数据
et = etree.HTML(resp.text)
divs = et.xpath("//div[@class='new-service-wrap']/div")
for div in divs:
# 此时的div就是一条数据. 对应一个商品信息
# 商品价格
price = div.xpath("./div/div/a/div[2]/div[1]/span[1]/text()")
if not price: # 过滤掉无用的数据
continue
price = price[0]
company = div.xpath("./div/div/a[2]/div[1]/p/text()")[0]
# name = div.xpath("./div/div/a[1]/div[2]/div[2]/p//text()") # //表示提取p的所有文本, 包括子子孙孙所有内容
# name = "".join(name)
print(company)
# r = "_".join(["张无忌", "麻花藤", "码云"])
# print(r)
//********************** Pyquery
from pyquery import PyQuery
html = """
<ul>
<li class="aaa"><a href="http://www.google.com">谷歌</a></li>
<li class="aaa"><a href="http://www.baidu.com">百度</a></li>
<li class="bbb" id="qq"><a href="http://www.qq.com">腾讯</a></li>
<li class="bbb"><a href="http://www.yuanlai.com">猿来</a></li>
</ul>
"""
# 加载html内容
p = PyQuery(html)
print(p)
print(type(p))
# pyquery对象直接(css选择器)
a = p("a")
print(a)
print(type(a)) # 依然是pyquery对象
# 链式操作
a = p("li")("a")
print(a)
a = p("li a")
print(a)
a = p(".aaa a") # class="aaa" aaa类的a标签
print(a)
a = p("#qq a") # id="qq"
print(a)
href = p("#qq a").attr("href") # 拿属性
text = p("#qq a").text() # 拿文本
print(text)
# 坑, 如果多个标签同时拿属性. 只能默认拿到第一个
href = p("li a").attr("href")
print(href)
# 多个标签拿属性
it = p("li a").items()
for item in it: # 从迭代器中拿到每一个标签
href = item.attr("href") # 拿到href属性
text = item.text()
print(text, href)
# 快速总结:
# 1. pyquery(选择器)
# 2. items() 当选择器选择的内容很多的时候. 需要一个一个处理的时候
# 3. attr(属性名) 获取属性信息
# 4. text() 获取文本
div = """
<div><span>我爱你</span></div>
"""
p = PyQuery(div)
html = p("div").html() # 全都要
text = p("div").text() # 只要文本, 所有的HTML标签被过滤掉
print(html) # <span>我爱你</span>
print(text) # 我爱你
html = """
<HTML>
<div class="aaa">哒哒哒</div>
<div class="bbb">嘟嘟嘟</div>
</HTML>
"""
p = PyQuery(html)
# 在xxxx标签后面添加xxxxx新标签
p("div.aaa").after("""<div class="ccc">吼吼吼</div>""")
p("div.aaa").append("""<span>我爱你</span>""")
p("div.bbb").attr("class", "aaa") # 修改属性
p("div.bbb").attr("id", "12306") # 新增属性, 前提是该标签没有这个属性
p("div.bbb").remove_attr("id") # 删除属性
p("div.bbb").remove() # 删除标签
print(p)
dic = {}
dic['jay'] = "周杰伦"
print(dic)
dic['jay'] = "呵呵哒"
print(dic)
//**************** pyquery实战案例
# pyquery 处理页面结构不规整的个情况 强行塞入确实部分,使结构完整
"""
1, 提取页面源代码
2, 解析页面源代码. 提取数据
"""
import requests
from pyquery import PyQuery
def get_page_source(url):
resp = requests.get(url)
resp.encoding = "gbk"
return resp.text
def parse_page_source(html):
doc = PyQuery(html)
mt_list = doc(".mt-10").items() # class="mt-10"
for mt in mt_list: # 拿到每一个mt
# 判断是否有汽车经销商
if not mt("div > dl:nth-child(3) > dt:contains(购车经销商)"):
# 向 地点 后添加购车经销商进去
mt("div > dl:nth-child(2)").after(PyQuery("""<dl class="choose-dl">
<dt>购车经销商</dt>
<dd>
<a href="###" class="js-dearname" data-val='125965,47759' data-evalid="3629818" target="_blank">
 
</a>
</dd>
</dl>"""))
# 提取购买的车型
# 想要在已经提取的内容中获取第一个怎么办? eq(0)
# nth-child(1) 在css进行选择的时候.选取第1个位置的内容
chexing = mt("div > dl:nth-child(1) > dd").eq(0).text().replace("\n", "").replace(" ", "")
didian = mt("div > dl:nth-child(2) > dd").text()
shijian = mt("div > dl:nth-child(4) > dd").text()
jiage = mt("div > dl:nth-child(5) > dd").text().replace(" 万元", "")
youhao = mt("div > dl:nth-child(6) > dd > p:nth-child(1)").text().replace(" 升/百公里", "")
gonglishu = mt("div > dl:nth-child(6) > dd > p:nth-child(2)").text().replace(" 公里", "")
other = mt("div > div > dl > dd").text().split()
print(other)
# 存储到文件中.......
def main():
url = "https://k.autohome.com.cn/146/"
# 1, 提取页面源代码
html = get_page_source(url)
# 2, 解析页面源代码.提取数据
parse_page_source(html)
if __name__ == '__main__':
main()
//********** 结束 数据解析部分
爬虫 解析数据
最新推荐文章于 2024-07-07 22:25:52 发布