声明:网站根目录下的robots.txt一般写了爬虫的协议,请遵守道德,不要乱爬,出了事别说是我教的。
一、三国演义下载(request)
import requests
url = "http://10.163.72.55:7777/image/sanguo1.md"
res = requests.get(url)
print(res.status_code) #打印对象的响应状态码,以检查请求是否成功
print(res.text) #把对象的文本以字符串的形式返回
# 创建一个名为三国演义的txt文档,以写模式打开
file = open("三国演义.txt","w")
# 写进文件中,相当于—— 蔡徐坤.吃饭("包子")
file.write(res.text)
# 关闭文档,相当于—— 蔡徐坤.睡觉()
file.close()
练习:获取http://10.163.72.55:7777/image/HTTP.md
扩展任务:批量爬取三国演义前三章
二、爬取一张图片(request)
import requests
url = 'http://10.163.72.55/img/angry.55b2c9de.gif'
res = requests.get(url)
print(res.status_code) #打印对象的响应状态码,以检查请求是否成功
print(res.content) #打印对象的二进制编码内容
# 新建了一个文件angry.jpg,这里的文件没加路径,它会被保存在程序运行的当前目录下。
# 图片内容需要以二进制wb读写。
photo = open('angry.jpg','wb')
# 获取pic的二进制内容
photo.write(res.content)
# 关闭文件
photo.close()
练习:我网站的所有图片,自己爬着玩吧
三、爬取一段视频(request)
import requests
url = 'http://10.163.72.55/media/banner3.043818a0.mp4'
res = requests.get(url)
print(res.status_code) #打印对象的响应状态码,以检查请求是否成功
print(res.content) #打印对象的二进制编码内容
# 新建了一个文件banner.mp4,这里的文件没加路径,它会被保存在程序运行的当前目录下。
# 图片内容需要以二进制wb读写。
video = open('banner.mp4','wb')
# 获取pic的二进制内容
video.write(res.content)
# 关闭文件
video.close()
四、豆瓣电影top250爬虫(静态网页bs4)
import requests,openpyxl
from bs4 import BeautifulSoup
wb=openpyxl.Workbook()
sheet=wb.active
sheet.title='豆瓣'
sheet['A1']='电影名'
sheet['B1']='评分'
sheet['C1']='推荐语'
sheet['D1']='链接'
for i in range(10):
url='http://10.163.72.55/%E8%B1%86%E7%93%A3%E7%94%B5%E5%BD%B1%20Top%20250.html?start='+str(i)+'&filter='
# url='https://movie.douban.com/top250?start='+str(i)+'&filter='
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
res=requests.get(url,headers=headers)
soup=BeautifulSoup(res.text,'html.parser')
movies=soup.find_all(class_="info")
for movie in movies:
href=movie.find('a')['href']
name=movie.find(class_="title").text
star=movie.find(class_="rating_num").text
quote=movie.find(class_="quote").text
sheet.append([name,star,quote,href])
print(href+name+star+quote)
wb.save('.\豆瓣爬虫的数据.xlsx')
五、机房管理系统爬虫(静态网页bs4)
爬取教师姓名的缩写,你们懂的,这个姓名缩写同时也是ftp的账号,可以用来爆破ftp的密码。
import requests,re
from bs4 import BeautifulSoup
txt=open('./teacher_name.txt','a')
url='http://10.163.72.11/index/admin/teacher'
headers={'user-agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'}
res=requests.get(url,headers=headers)
soup=BeautifulSoup(res.text,'html.parser')
items = soup.find_all('h5',class_='card-title')
for item in items:
name = re.search(r'【.*】',item.text).group()
name = name[1:] #去掉前面的括号
name = name[:-1] #去掉前面的括号
print(name)
txt.write(name + 'down' + '\n')
txt.close()
六、爬取神秘暗网留言板(动态网站json)
import requests,openpyxl
wb = openpyxl.Workbook()
sheet = wb.active
sheet.title = '留言数据'
sheet['A1'] = '用户ID'
sheet['B1'] = '用户名'
sheet['C1'] = '积分'
sheet['D1'] = '留言内容'
# 爬取前十页
for i in range(1,10):
url = 'http://10.163.72.55/messageData.php?currentPage='+str(i)
res = requests.get(url)
res_jons = res.json() # 解析为json格式数据
print(type(res_jons))
massage_list = res_jons['data']
for item in massage_list:
id = item['id']
username = item['username']
rankScore = item['rankScore']
message = item['message']
sheet.append([id,username,rankScore,message])
wb.save('.\神秘暗网留言板爬虫.xlsx')
七、带着参数请求数据(偷看隐藏数据)
假设神秘暗网首页作业栏目,不可以点击查看更多,可以携带参数查看隐藏信息。
import requests
url = 'http://10.163.72.55/taskListData.php'
params = {'task_num':3}
res = requests.get(url,params=params)
res_json = res.json()
task_list = res_json['data']
for task in task_list:
print('作业标题为:',task['title'])
假设用户管理中,教师组属于敏感信息,不让普通用户查询,你知道该怎么做了吧。
import requests
url = 'http://10.163.72.55/userAdminDataClass.php'
params = {'className':'22计2'}
res = requests.get(url,params=params)
res_json = res.json()
user_list = res_json['data']
for user in user_list:
print('用户姓名为:',user['username'])
八、指挥浏览器登录神秘暗网(自动脚本)
from selenium import webdriver # 从selenium库中调用webdriver模块
from selenium.webdriver.common.by import By
import time
driver=webdriver.Chrome()
driver.get('http://10.163.72.55/#/index/IndexTask') # 访问页面
time.sleep(2) # 暂停两秒,等待浏览器缓冲
login = driver.find_element(By.ID,'login')
login.click() # 点击【提交】按钮
username = driver.find_element(By.ID,'username') # 找到用户名输入框位置
username.send_keys('你的名字') # 输入文字
password = driver.find_element(By.ID,'password') # 找到密码输入框位置
password.send_keys(123456)
login_button = driver.find_element(By.CLASS_NAME,'login_button') # 找到密码输入框位置
login_button.click()
九、通过cookie留言(突破留言板限制)
import requests
#获得cookies
url='http://10.163.72.55/LoginPost.php'
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'}
data={
'username': 'username',
'password': 'password',
}
login=requests.post(url,headers=headers,data=data)
cookies=login.cookies
print(cookies)
#用cookies登陆
url_2='http://10.163.72.55/messagePost.php'
params = {'gb_word':'没想到吧,我还是可以留言,哈哈'}
res=requests.get(url_2,cookies=cookies,headers=headers,params=params)
res_json = res.json()
print(res_json)
十、使用scrpit框架爬豆瓣
pip install scrapy -i https://pypi.tuna.tsinghua.edu.cn/simple/ # 安装环境
scrapy startproject douban # 创建项目
scrapy crawl douban #运行工程
爬虫模块
# (爬虫)部门是公司的核心业务部门
# 负责创建requests对象和接受引擎发送过来的response(Downloader部门爬取到的内容),从中解析并提取出有用的数据。
# 它对应的是爬虫流程【解析数据】和【提取数据】这两步
import scrapy
import bs4
# 需要引用DoubanItem,它在items里面。因为是items在top250.py的上一级目录,所以要用..items,这是一个固定用法。
from ..items import DoubanItem
# DoubanSpider类继承自scrapy.Spider类
class DoubanSpider(scrapy.Spider):
name = 'douban' # 定义爬虫的名字,这个名字是爬虫的唯一标识
# allowed_domains是定义允许爬虫爬取的网址域名(不需要加https://)。
# 如果网址的域名不在这个列表里,就会被过滤掉
# 一定在book.douban.com这个域名之下,防止爬到广告页面去
allowed_domains = ['book.douban.com']
# 定义起始网址,就是爬虫从哪个网址开始抓取
# 注:allowed_domains的设定对start_urls里的网址不会有影响
start_urls = ['https://book.douban.com/top250?start=0']
# 根据url的规律,构建出前三页地址
start_urls = []
for x in range(3):
url = 'https://book.douban.com/top250?start=' + str(x * 25)
start_urls.append(url)
# 解析下载器传过来的数据
def parse(self, response):
# 爬取的数据存储在response.text
bs = bs4.BeautifulSoup(response.text,'html.parser')
datas = bs.find_all('tr',class_="item")
for data in datas:
#实例化DoubanItem类。
item = DoubanItem()
# 书名
item['title'] = data.find_all('a')[1]['title']
#提取出出版信息,并把这个数据放回DoubanItem类的publish里。
item['publish'] = data.find('p',class_='pl').text
# 评分
item['score'] = data.find('span',class_='rating_nums').text
print(item['title'])
#yield item是把获得的item传递给引擎。
#有点类似return,不过它和return不同的点在于,它不会结束函数,且能多次返回信息
yield item
数据处理模块
# (数据管道)部门则是公司的数据部门
# 只负责存储和处理Spiders部门提取到的有用数据。这个对应的是爬虫流程【存储数据】这一步。
import scrapy
#定义一个类DoubanItem,它继承自scrapy.Item
class DoubanItem(scrapy.Item):
# scrapy.Field() 相当于自定义字典类型
title = scrapy.Field() #定义书名的数据属性
publish = scrapy.Field() #定义出版信息的数据属性
score = scrapy.Field() #定义评分的数据属性
# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
# 是否需要遵守爬虫规则,改成不遵守
ROBOTSTXT_OBEY = False
设置
# 保存爬取的数据
FEED_URI='./storage/data/%(name)s.csv'
FEED_FORMAT='csv'
FEED_EXPORT_ENCODING='ansi' # 导出文件编码,ansi是一种在windows上的编码格式
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
# 是否需要遵守爬虫规则,改成不遵守
ROBOTSTXT_OBEY = False
# 爬虫的速度
DOWNLOAD_DELAY = 0.5
主程序启动模块 (和scrapy.cfg同级)
#导入cmdline模块,可以实现控制终端命令行。
from scrapy import cmdline
#用execute()方法,输入运行scrapy的命令。
cmdline.execute(['scrapy','crawl','douban'])
作业:爬取当当网前三页,书名,作者,价格
http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-year-2018-0-1-1
扩展提升
爬取每一条新闻里的内容
http://www.news.zjut.edu.cn/5415/list.htm
# (爬虫)部门是公司的核心业务部门
# 负责创建requests对象和接受引擎发送过来的response(Downloader部门爬取到的内容),从中解析并提取出有用的数据。
# 它对应的是爬虫流程【解析数据】和【提取数据】这两步
import scrapy
import bs4
# 需要引用DoubanItem,它在items里面。因为是items在top250.py的上一级目录,所以要用..items,这是一个固定用法。
from ..items import DoubanItem
# DoubanSpider类继承自scrapy.Spider类
class DoubanSpider(scrapy.Spider):
name = 'douban' # 定义爬虫的名字,这个名字是爬虫的唯一标识
# allowed_domains是定义允许爬虫爬取的网址域名(不需要加https://)。
# 如果网址的域名不在这个列表里,就会被过滤掉
# 一定在book.douban.com这个域名之下,防止爬到广告页面去
allowed_domains = ['www.news.zjut.edu.cn']
# 定义起始网址,就是爬虫从哪个网址开始抓取
# 注:allowed_domains的设定对start_urls里的网址不会有影响
start_urls = ['http://www.news.zjut.edu.cn/5415/list.htm']
# 解析下载器传过来的数据
def parse(self, response):
# 爬取的数据存储在response.text
bs = bs4.BeautifulSoup(response.text,'html.parser')
datas = bs.find_all('span',class_="news_title")
for data in datas:
href = data.find('a')['href']
link = 'http://www.news.zjut.edu.cn/5415/list.htm' + href
# 链接先爬下来回传给引擎,引擎通过调度器给下载器,下载好了再传给我
yield scrapy.Request(link, callback=self.parse2)
#这个就是下载器下载好的数据
def parse2(self, response):
bs = bs4.BeautifulSoup(response.text,'html.parser')
item = DoubanItem()
item['title'] = bs.find(class_='arti_title').text
yield item
十一、破解并下载视频流
import requests,re,random
from Crypto.Cipher import AES
# 伪装请求头
user_agent = [
'Mozilla/5.0 (Windows NT 5.2) AppleWebKit/534.30 (KHTML, like Gecko) Chrome/12.0.742.122 Safari/534.30',
'Mozilla/5.0 (Windows NT 5.1; rv:5.0) Gecko/20100101 Firefox/5.0',
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET4.0E; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C)',
'Opera/9.80 (Windows NT 5.1; U; zh-cn) Presto/2.9.168 Version/11.50',
'Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1',
'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET4.0E; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C)',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'
]
headers = {'User-Agent': random.choice(user_agent)}
url = 'http://www.nvic.edu.cn/CompetitionVideo/Detail?worksId=3ddcd2d0-39f1-49b8-83a2-03b8e5ef780d&sType=5&competitionId=ce116ee4-ca64-4c16-9aff-750fed3335cf'
res = requests.get(url,headers=headers)
# 获取几个独立视频的链接
pattern=re.compile('data-path="(.*?)"')
indexs_list=re.findall(pattern,res.text)
for index in indexs_list:
# 获取视频文件存放路径
path = index[:-10]
res = requests.get(index,headers=headers)
pattern=re.compile('URI="(.*?.key)"')
key= re.findall(pattern,res.text)[0]
key_url = path + key # 拼凑出key的地址
print(key_url)
key_res = requests.get(key_url) # 拿到key的内容
print('已获取到key')
print(key_res.content)
aes = AES.new(key_res.content, AES.MODE_CBC, b'0000000000000000') # 制作解密文件
print('已成功制作解密文件')
# 拿视频碎片
pattern=re.compile('(filesequence\d+.ts)')
filesequences_list=re.findall(pattern,res.text)
count = 1 # 计数、缓解等待压力
for filesequence in filesequences_list:
filesequence_url = path + filesequence
res = requests.get(filesequence_url,headers=headers)
# 图片内容需要以二进制wb读写。
video = open(f'{key}.mp4','ab+')
# 获取pic的二进制内容
video.write(aes.decrypt(res.content))
# 关闭文件
video.close()
count += 1
print("\r[下载进度]:{}{:.2f}%".format('>'*count,count/len(filesequences_list)*100),end='')
十二、新遇到的一点反爬问题
最近爬这个网站遇到一点问题,https://www.ly.com/hotel/hotellist?pageSize=20&t=1693794571107&city=321&inDate=2023-09-04&outDate=2023-09-05&filterList=8888_1
以前可以爬,现在不能爬,经过研究,发现是网站开发者增加了对请求头字段的校验。
import requests
headers_str = '''accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
accept-language: zh-cn
appfrom: 16
cluster: idc
Connection: keep-alive
Cookie: soso_17u_tab_open_index=1; H5CookieId=2a31035b-81b0-452f-8af5-4bc2cb6d6229; firsttime=1693790207090; abtkey=037eed29-b152-4fc3-92a8-027faa2dffc6; _tcudid_v2=GVAglBHWXx1wFDh4_P4gvwe79p_DO7Vf2Yj7sQ9vCd4; nus=userid=682242716&nickName=%e5%90%8c%e7%a8%8b%e4%bc%9a%e5%91%98_0D043E7512A&level=1; __tctma=144323752.1693790169808694.1693790169437.1693790169437.1693793067529.2; hotel_lang=zh-cn; 17uCNRefId=RefId=0&SEFrom=&SEKeyWords=; TicketSEInfo=RefId=0&SEFrom=&SEKeyWords=; CNSEInfo=RefId=0&tcbdkeyid=&SEFrom=&SEKeyWords=&RefUrl=; qdid=-9999; businessLine=hotel; H5Channel=mnoreferseo%2CSEO; indate=2023-09-09; outdate=2023-09-10; route=e83eaebd8f07fc1b8cfab528aeb2900e; lasttime=1694239332948; JSESSIONID=A23D8BD953AE131A1233B6F406759B2E
deviceid: 2a31035b-81b0-452f-8af5-4bc2cb6d6229
Host: www.ly.com
Referer: https://www.ly.com/hotel/hotellist?pageSize=20&t=1694239332807&city=321&inDate=2023-09-09&outDate=2023-09-10&filterList=8888_1
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
timezone: 8
tmapi-client: tpc
traceid: d6d36af2-7f3a-4504-a125-db1cfa470c97
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36'''
headers_dict = {}
line_list = headers_str.split('\n')
for line in line_list:
key = line.split(':')[0]
value = line.split(':')[1]
headers_dict[key] = value.strip()
# print(headers_dict)
url = 'https://www.ly.com/tapi/v2/list?pageSize=20&t=1694239311116&city=321&inDate=2023-09-09&outDate=2023-09-10&filterList=8888_1&pageIndex=0&sugActInfo='
res = requests.get(url,headers=headers_dict)
res_json = res.json()
hotel_list = res_json['data']['hotelList']
for hotel in hotel_list:
hotelName = hotel['hotelName']
print(hotelName)