收集豆瓣电影 TOP250 信息
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
"""
豆瓣电影
1. 构造 requests 抓取网页源代码
2. 对源码进行正则表达式分析
3. 提出数据,直接显示或者存储进文件中
"""
import re
import requests
f = open("top250.csv", mode="w", encoding='utf-8')
url = "https://movie.douban.com/top250"
headers = {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36'
}
for i in range(0, 251, 25):
params = {
'start': str(i),
'filter': '',
}
resp = requests.get(url, headers=headers, params=params)
pageSource = resp.text
"""
排名: xx
电影名: xxx
评分: xx
点评: xxxx
"""
obj = re.compile(
r'<div class="item">.*?<em class="">(?P<rank>.*?)</em>.*?<span class="title">(?P<name>.*?)</span>.*?property="v:average">(?P<score>.*?)</span>.*?<span class="inq">(?P<appraisal>.*?)</span>',
re.S)
result = obj.finditer(pageSource)
for item in result:
rank = item.group("rank")
# print("排名: " + rank)
name = item.group("name")
# print("电影名: " + name)
score = item.group("score")
# print("评分: " + score)
appraisal = item.group("appraisal")
# print("点评: " + appraisal + '\n')
f.write(f"{rank},{name},{score},{appraisal}\n")
f.close()
resp.close()
print("豆瓣电影 TOP250 信息收集完毕")
收集实习僧--信息安全实习岗位信息
参考文章:python爬虫爬取实习僧岗位信息并存入excel数据表中
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
"""
爬取实习僧--信息安全实习岗位
1. 爬取代码源数据存储至 html 文件中,参考源代码与页面对应的位置
f = open("reference.html", mode="w", encoding='utf-8')
f.write(resp.text)
2. 爬取过后,实习僧可能会禁用爬取的 IP 一段时间,此时可以在 html 文件中做参考(也可以使用代理池,但目前我不会)
f = open("reference.html", mode="r", encoding='utf-8')
data = f.read()
3. 查阅了大佬的博客发现数字是加密了的,需要相关文件解密,源代码相关内容如下
@font-face { font-family: myFont; src: url(/interns/iconfonts/file?rand=0.8686403770606255);}
4. 将下载的字体文件放进同目录文件下,重命名后缀为 .ttf,并解析成 xml 文件
from fontTools.ttLib import TTFont
font = TTFont("file.ttf")
font.saveXML("font.xml")
5. 使用表达式提取并转换对应的 HTML 实体,做一个字典,并做一个用于转换的函数
6. 将提取出的数据整合,并存储进 md 文件中
PS: 实习僧的加密字体文件每天都会变化,因此可以选择制作一个自动化脚本实现下载解密文件 + 解析 xml 文件 + 爬取网页信息并整合,但我嫌麻烦,所以就手动下载了
"""
import re
import requests
def get_dict():
# 打开并读取 font.xml
with open('font.xml') as f:
xml = f.read()
f.close()
# 正则表达式提取 code 和 name
keys = re.findall('<map code="(0x.*?)" name="uni.*?"/>', xml)
values = re.findall('<map code="0x.*?" name="uni(.*?)"/>', xml)
word_dict = {}
# 将 name 解码成中文并作为值写入字典 word_dict,该字典的键为 keys
for i in range(len(values)):
if len(values[i]) < 4:
values[i] = ('\\u00' +
values[i]).encode('utf-8').decode('unicode_escape')
else:
values[i] = ('\\u' +
values[i]).encode('utf-8').decode('unicode_escape')
word_dict[keys[i]] = values[i]
# print(word_dict)
return word_dict
dict = get_dict()
def char_decode(str):
while ('&#' in str):
tmp = str.find('&#')
str = str.replace('&#', '0', 1)
key = str[tmp:tmp + 6]
value = dict[key]
str = str.replace(key, value, 1)
# print(str)
return str
url_head = "https://www.shixiseng.com/interns?page="
url_tail = "&type=intern&keyword=信息安全&area&months&days°ree&official&enterprise&salary=-0&publishTime&sortType&city=全国&internExtend"
for i in range(28):
url = url_head + str(i) + url_tail
resp = requests.get(url)
"""
岗位: xxx
公司: xxx
薪资: xxx
地区: xxx
工作时间: xxx
实习时长: xxx
公司信息: xxx
截至日期: xxx
"""
data = resp.text
f = open("info.md", "a+", encoding='utf-8')
obj = re.compile(
r'<p data-v-7c5681ee><a href="(?P<link>.*?)" title=.*?class="title ellipsis font" data-v-7c5681ee>(?P<post>.*?)</a>.*?day font" data-v-7c5681ee>(?P<salary>.*?)</span>.*?city ellipsis" data-v-7c5681ee>(?P<location>.*?)</span>.*?font" data-v-7c5681ee>(?P<worktime>.*?)</span>.*?font" data-v-7c5681ee>(?P<workdays>.*?)</span>.*?data-v-7c5681ee><a title="(?P<company>.*?)" href.*?"font" data-v-7c5681ee>(?P<info>.*?)</span>',
re.S)
obj2 = re.compile(
r'<div class="cutom_font" data-v-6d86e756>截止日期:(?P<deadline>.*?)</div>',
re.S)
result = obj.finditer(data)
for item in result:
link = item.group("link")
company = item.group("company")
f.write("公司: " + company + '\n')
# print("公司: " + company)
salary = item.group("salary")
f.write("薪资: " + char_decode(salary) + '\n')
# print("薪资: " + char_decode(salary))
post = item.group("post")
f.write("岗位: " + '[' + char_decode(post) + '](' + link + ')' + '\n')
# print("岗位: " + char_decode(post))
location = item.group("location")
f.write("地区: " + location + '\n')
# print("地区: " + location)
worktime = item.group("worktime")
f.write("工作时间: " + char_decode(worktime) + '\n')
# print("工作时间: " + char_decode(worktime))
workdays = item.group("workdays")
f.write("实习时长: " + char_decode(workdays) + '\n')
# print("实习时长: " + char_decode(workdays))
info = item.group("info")
f.write("公司信息: " + char_decode(info) + '\n')
# print("公司信息: " + char_decode(info))
# 下一个网页提取开始
url2 = link
resp2 = requests.get(url2)
result2 = obj2.finditer(resp2.text)
for item2 in result2:
deadline = item2.group("deadline")
f.write("截至日期: " + deadline + '\n')
# print("截至日期: " + deadline)
# 下一个网页提取结束
f.write('\n\n\n')
# print()
f.close()
resp.close()
print("实习僧--信息安全实习岗位信息收集完毕")
爬取结果如下:
收集涂鸦王国--精选作品
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
"""
爬取涂鸦王国--精选作品
1. 找到目标图片所在的父结点的属性 class="col-6 col-lg-3 mb-4"
2. 创建文件夹,此文件夹将存储爬取的图片
3. 继续查找图片 url 的属性 class="d-flex setgray" 和图片名字的属性 class="pt-2 font-weight-bold font-13 text-truncate pb-2"
4. 请求图片的 url,将返回结果以二进制的方式存储为图片并命名,放至文件夹中
PS: 相比于正则 re,bs4 更擅长处理非格式化的 HTML 源代码
PS: 浏览器显示源代码与爬取的源代码存在不一致的情况,以爬取的源代码为准
PS: 国外的插画网站不容易连接,需要手动下载源码,且仅支持不需要翻页的网页,因此不予演示
"""
from bs4 import BeautifulSoup
import requests
import re
import os
url = "https://www.gracg.com/works/best.more?type=jingxuan"
resp = requests.get(url)
html = resp.text
page = BeautifulSoup(html, "html.parser")
# print(page)
paints = page.find_all("div", attrs={"class": "col-6 col-lg-3 mb-4"})
os.makedirs("涂鸦王国")
for paint in paints:
data = paint.find("a", attrs={"class": "d-flex setgray"})
result = data.get("style")
img_url = re.search(r"background:url\((?P<url>.*?)\?", result)
url = img_url.group("url")
# print(url)
img_resp = requests.get(url)
data2 = paint.find("div", attrs={"class": "pt-2 font-weight-bold font-13 text-truncate pb-2"})
name = data2.text
# print(name)
with open(f"涂鸦王国/{name}.jpg", mode="wb") as f:
f.write(img_resp.content)
f.close()
resp.close()
print("涂鸦王国--精选作品收集完毕")
爬取结果如下:
获取猪八戒--python外包公司信息
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
"""
爬取猪八戒--python外包公司信息
1. 将目标网页源代码存储至 reference.html 并格式化
2. 使用 F12 查看目标网页模块源代码,找到标签 search-result-list-service
3. 打开 reference.html,删除该标签以外的全部无用模块,因为仅需要考虑该模块的内部内容
4. 找到公司名称、标题、价格、好评这四个对应的标签路径
5. 利用 xpath 获取目标公司信息
PS: xpath 匹配的索引是从 1 开始
PS: 当匹配目标属性值中含有空格或横杠 [' ' or '-'],那么最好换另一种匹配方法
"""
from lxml import etree
import requests
url = "https://zhuhai.zbj.com/search/service?l=0&kw=python&r=1"
resp = requests.get(url)
html = resp.text
"""
# 保存至本地
f = open("reference.html", mode="w", encoding='utf-8')
f.write(html)
"""
et = etree.HTML(html)
divs = et.xpath("//div[@class='search-result-list-service']/div")
for div in divs:
company = div.xpath(
"./div[2]/a/div[2]/div[1]/div[1]/text()")[0].strip().replace('\n', '')
# print(company)
title = div.xpath("./div[2]/a/text()")[0].strip().replace('\n', '')
# print(title)
price = div.xpath("./*/div[@class='price']/span/text()")[0]
# print(price)
comment = div.xpath("./*/div[@class='price']/div/span[2]/text()")[0]
# print(comment)
infomation = " ".join(["公司名:", company, "标题:", title, "价格:", price, "好评:", comment])
print(infomation)
print("收集猪八戒--python外包公司信息完毕")
爬取微博视频--某博主的视频(使用代理池)
参考文章:Python学习笔记:requests请求传递Query String Parameters参数及提交From Data数据
参考视频:【python爬虫】爬取微博宅舞区视频,看的我心旷神怡吖~
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
"""
爬取微博视频--某博主的视频
1. 进入博主视频页,找到包含视频列表的包 getWaterFallContent?uid=xxx&&cursor=0,使用 Postman 测试可以正常响应数据
2. 记录该包每个视频对应的 oid,并点击进入第一个视频,发现视频网址的格式为 https://weibo.com/tv/show/{oid}?from=old_pc_videoshow
3. 找到包含可下载视频信息的包(包含 mp4 格式的视频)component?page=%2Ftv%2Fshow%2Fxxx%3Axxx,使用 Postman 测试不能正常响应数据
4. 经过测试发现请求头需要携带 cookie 和 referer(后者为防盗链,原理自行百度),之后进行常规操作:写代码
5. 使用代理池(可忽略)
PS: 使用 Postman 的目的是查看请求包是否能单独请求,如果不能,则可能是需要携带参数(如 referer)
PS: 稍微做个记录,便于以后再用(其中 {temp} 代表随机字符串)
- 微博视频网址(有多种)
https://weibo.com/tv/show/1034:{temp1}?mid={temp2}
https://weibo.com/tv/show/{temp1}:{temp2}?from=old_pc_videoshow
- 微博视频的抓包名
component?page=%2Ftv%2Fshow%2F{temp1}%3A{temp2}
- 上面抓到包其实有多个重名的,其中所包含的信息也不同
分别含有视频信息、弹幕信息、评论信息、推荐列表信息等
- 微博视频的请求网址
https://weibo.com/tv/api/component?page=%2Ftv%2Fshow%2F{temp1}%3A{temp2}
- 可以下载的视频链接(有多种,位于响应包 Video[data][Component_Play_Playinfo][urls])
高清 1080P: "//live.video.weibocdn.com/{temp1}.m3u8?{temp2}&ssig={temp3}&KID=unistore,video"
高清 1080P: "//f.video.weibocdn.com/o0/{temp1}.mp4?{temp2}&ssig={temp3}&KID=unistore,video"
- 爬取视频的流程
1. 推荐视频首页 / 博主视频页 -> 记录视频网址列表
2. 进入其中一个视频网址 -> 记录请求网址、视频下载链接、防盗链
3. 爬取全部视频
PS: 观察了多个微博视频不同的网址,有了如下发现
- 在推荐视频首页(https://weibo.com/tv/home)
热门视频有 3 个,推荐视频默认 9 个,如果往下刷新,响应包会继续更新
每个视频对应的网址位于响应包 Video[data][Component_Channel_Menu][list],包含 media_id、oid 和 mid
- 在博主的视频页(https://weibo.com/u/xxx?tabtype=newVideo)
默认视频有 20 个,同样的,如果往下刷新,响应包页会继续更新
每个视频对应的网址位于响应包 [list][data][num(视频列表)][url_struct][0][actionlog][oid],包含 oid
- 不同的视频类型
只有明星的视频下载网址才是 m3u8,普通用户或大 V 的视频下载网址是 mp4
理论上前者的视频格式播放速度是远快于后者,且占用资源更多(原因自行百度),缘由应该是粉丝访问基数太大
"""
import requests
def get_ip():
# 反复提取代理 ip
while 1:
# 快代理的 ip 池
url = "https://ent.kdlapi.com/api/getproxy/xxx"
resp = requests.get(url)
ips = resp.json()
if ips['code'] == 0:
for ip in ips['data']['proxy_list']: # 拿到每一个 ip
print("正在使用的代理ip:", ip)
yield ip # 一个一个返回代理 ip
print("所有 ip 已经用完, 即将更新!") # for 循环结束,继续提取新 ip
else:
print("获取代理 ip 出现异常,重新获取!")
def spider():
VideoListURL = "https://weibo.com/ajax/profile/getWaterFallContent?uid=7417986528&cursor=0"
_VideoURL = "https://weibo.com/tv/api/component?page=%2Ftv%2Fshow%2F1034%3A"
while 1:
try:
proxy_ip = next(gen) # 拿到代理 ip
proxies = {"http": proxy_ip}
headers = {
"cookie":
"XSRF-TOKEN=8-qZNWdSbKsiamPHyozxqwFW; UPSTREAM-V-WEIBO-COM=b09171a17b2b5a470c42e2f713edace0; _s_tentry=-; Apache=1355041230414.402.1655483749477; SINAGLOBAL=1355041230414.402.1655483749477; ULV=1655483749610:1:1:1:1355041230414.402.1655483749477:; SSOLoginState=1656495744; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9WW5nJX_-MQO7xqQqvM-Xceq5JpX5KMhUgL.Foq41h5R1hnpShn2dJLoIp7LxKML1KBLBKnLxKqL1hnLBoMc1Kn71hnReKBR; ALF=1689218329; SCF=Aou9Itrp6glWp11idjzzspo8N_wqfHsFQqqa1JA9eOhGYlOaa7PLN30ZKWJ-k3JL_VNVOVU9ZSZeF5Y_nnzfv_c.; SUB=_2A25PyknLDeRhGeBH41IZ-CbNzzSIHXVsvjwDrDV8PUNbmtANLWqmkW9NQbiusC0nt6udPV9Dy81zsyo3G8u_G81J; UOR=,,www.qishe.org; WBPSESS=gvuJu6QavEC3mI3rC_-E-YqpQjRVYdjo2ix520eibeabVoMSe9WxqEZdwePTINaLrYyCDZZfNFb3HMiFIAnnYKvITw8-dTMIVBLvs80ukOewNoPSYWzCegUQvNl2vhBIh9RORAsi8a_LP_XwI3XowA==; PC_TOKEN=c24052de70"
}
resp = requests.get(VideoListURL, proxies=proxies, headers=headers)
resp.encoding = "utf-8"
VideoListJson = resp.json()['data']['list']
# 此包一次存储 20 个视频,如需要抓取剩下的包,请自行修改
count = 1
for VideoJson in VideoListJson:
oid = VideoJson['url_struct'][0]['actionlog']['oid']
_oid = oid.split(':')[1]
VideoURL = _VideoURL + _oid
# print(VideoURL)
headers = {
"cookie":
"XSRF-TOKEN=8-qZNWdSbKsiamPHyozxqwFW; UPSTREAM-V-WEIBO-COM=b09171a17b2b5a470c42e2f713edace0; _s_tentry=-; Apache=1355041230414.402.1655483749477; SINAGLOBAL=1355041230414.402.1655483749477; ULV=1655483749610:1:1:1:1355041230414.402.1655483749477:; SSOLoginState=1656495744; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9WW5nJX_-MQO7xqQqvM-Xceq5JpX5KMhUgL.Foq41h5R1hnpShn2dJLoIp7LxKML1KBLBKnLxKqL1hnLBoMc1Kn71hnReKBR; ALF=1689218329; SCF=Aou9Itrp6glWp11idjzzspo8N_wqfHsFQqqa1JA9eOhGYlOaa7PLN30ZKWJ-k3JL_VNVOVU9ZSZeF5Y_nnzfv_c.; SUB=_2A25PyknLDeRhGeBH41IZ-CbNzzSIHXVsvjwDrDV8PUNbmtANLWqmkW9NQbiusC0nt6udPV9Dy81zsyo3G8u_G81J; UOR=,,www.qishe.org; WBPSESS=gvuJu6QavEC3mI3rC_-E-YqpQjRVYdjo2ix520eibeabVoMSe9WxqEZdwePTINaLrYyCDZZfNFb3HMiFIAnnYKvITw8-dTMIVBLvs80ukOewNoPSYWzCegUQvNl2vhBIh9RORAsi8a_LP_XwI3XowA==; PC_TOKEN=c24052de70",
"referer":
f"https://weibo.com/tv/show/{oid}?from=old_pc_videoshow"
}
params = {"page": f"/tv/show/{oid}"}
# 下面这个 data 里面还包含 data 我是没想得到的,成功耗费了我两个小时 debug,充分的说明了该程序员的开发能力不足
data = {
'data': '{"Component_Play_Playinfo":{"oid":"' + oid + '"}}'
}
resp2 = requests.post(VideoURL, proxies=proxies, headers=headers, params=params, data=data)
resp2.encoding = "utf-8"
Video = resp2.json()['data']['Component_Play_Playinfo']['urls']['高清 1080P']
# 可在线播放的视频地址,也是我要下载的地址
Video = "https:" + Video
# print(Video)
with open(f"{count}.mp4", mode="wb") as f:
f.write(requests.get(Video).content)
count += 1
print("获取微博用户的视频成功")
return None # 运行成功后,强制返回
except:
print("报错了")
if __name__ == '__main__':
gen = get_ip() # 代理 ip 的生成器
spider()
爬取电影 emmm
实现自动化登入极验 / B 站 / 12306(绕过验证码)
推荐好文:利用selenium携带cookies实现免登录【可实现 selenium + cookies 的效果】
"""
实现自动化登入极验(Requests + 识别图片)
"""
"""
实现自动化登入 B 站(Selenium + 识别图片)
"""
"""
实现自动化登入 12306(Selenium + 拖动滑块)
"""
所有评论(0)