""""
反爬机制:门户网站,可以通过制定相应的策略或者技术手段,防止爬虫程序进行网站数据的爬取。
反反爬策略:爬虫程序可以通过制定相关的策略或者技术手段,破解门户网站中具备的反爬机制,从而可以获取门户网站中相关的数据。
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("美女图片下载完毕")
# 老师演示的时候,是去年的课程,还有点绿色。我现在打开,贼h。忍不住下载了几张~哈哈
//****************
Python 爬虫 继续
最新推荐文章于 2024-11-14 08:53:59 发布