收集豆瓣電影 TOP250 信息
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
"""
豆瓣電影
1. 構造 requests 抓取網(wǎng)頁源代碼
2. 對源碼進行正則表達式分析
3. 提出數(shù)據(jù),直接顯示或者存儲進文件中
"""
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數(shù)據(jù)表中
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
"""
爬取實習僧--信息安全實習崗位
1. 爬取代碼源數(shù)據(jù)存儲至 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. 查閱了大佬的博客發(fā)現(xiàn)數(shù)字是加密了的部念,需要相關文件解密襟己,源代碼相關內(nèi)容如下
@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 實體叹谁,做一個字典,并做一個用于轉換的函數(shù)
6. 將提取出的數(shù)據(jù)整合乘盖,并存儲進 md 文件中
PS: 實習僧的加密字體文件每天都會變化,因此可以選擇制作一個自動化腳本實現(xiàn)下載解密文件 + 解析 xml 文件 + 爬取網(wǎng)頁信息并整合憔涉,但我嫌麻煩订框,所以就手動下載了
"""
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
地區(qū): 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("地區(qū): " + location + '\n')
# print("地區(qū): " + 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))
# 下一個網(wǎng)頁提取開始
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)
# 下一個網(wǎng)頁提取結束
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. 創(chuàng)建文件夾兜叨,此文件夾將存儲爬取的圖片
3. 繼續(xù)查找圖片 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: 國外的插畫網(wǎng)站不容易連接,需要手動下載源碼跪但,且僅支持不需要翻頁的網(wǎng)頁履羞,因此不予演示
"""
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. 將目標網(wǎng)頁源代碼存儲至 reference.html 并格式化
2. 使用 F12 查看目標網(wǎng)頁模塊源代碼,找到標簽 search-result-list-service
3. 打開 reference.html,刪除該標簽以外的全部無用模塊忆首,因為僅需要考慮該模塊的內(nèi)部內(nèi)容
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("http://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參數(shù)及提交From Data數(shù)據(jù)
參考視頻:【python爬蟲】爬取微博宅舞區(qū)視頻,看的我心曠神怡吖~
#! /usr/bin/env python
# -*- coding: UTF-8 -*-
"""
爬取微博視頻--某博主的視頻
1. 進入博主視頻頁浸锨,找到包含視頻列表的包 getWaterFallContent?uid=xxx&&cursor=0唇聘,使用 Postman 測試可以正常響應數(shù)據(jù)
2. 記錄該包每個視頻對應的 oid,并點擊進入第一個視頻柱搜,發(fā)現(xiàn)視頻網(wǎng)址的格式為 https://weibo.com/tv/show/{oid}?from=old_pc_videoshow
3. 找到包含可下載視頻信息的包(包含 mp4 格式的視頻)component?page=%2Ftv%2Fshow%2Fxxx%3Axxx迟郎,使用 Postman 測試不能正常響應數(shù)據(jù)
4. 經(jīng)過測試發(fā)現(xiàn)請求頭需要攜帶 cookie 和 referer(后者為防盜鏈,原理自行百度)冯凹,之后進行常規(guī)操作:寫代碼
5. 使用代理池(可忽略)
PS: 使用 Postman 的目的是查看請求包是否能單獨請求谎亩,如果不能,則可能是需要攜帶參數(shù)(如 referer)
PS: 稍微做個記錄宇姚,便于以后再用(其中 {temp} 代表隨機字符串)
- 微博視頻網(wǎng)址(有多種)
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}
- 上面抓到包其實有多個重名的匈庭,其中所包含的信息也不同
分別含有視頻信息、彈幕信息浑劳、評論信息阱持、推薦列表信息等
- 微博視頻的請求網(wǎng)址
https://weibo.com/tv/api/component?page=%2Ftv%2Fshow%2F{temp1}%3A{temp2}
- 可以下載的視頻鏈接(有多種,位于響應包 Video[data][Component_Play_Playinfo][urls])
高清 1080P: "http://live.video.weibocdn.com/{temp1}.m3u8?{temp2}&ssig={temp3}&KID=unistore,video"
高清 1080P: "http://f.video.weibocdn.com/o0/{temp1}.mp4?{temp2}&ssig={temp3}&KID=unistore,video"
- 爬取視頻的流程
1. 推薦視頻首頁 / 博主視頻頁 -> 記錄視頻網(wǎng)址列表
2. 進入其中一個視頻網(wǎng)址 -> 記錄請求網(wǎng)址魔熏、視頻下載鏈接衷咽、防盜鏈
3. 爬取全部視頻
PS: 觀察了多個微博視頻不同的網(wǎng)址,有了如下發(fā)現(xiàn)
- 在推薦視頻首頁(https://weibo.com/tv/home)
熱門視頻有 3 個蒜绽,推薦視頻默認 9 個镶骗,如果往下刷新,響應包會繼續(xù)更新
每個視頻對應的網(wǎng)址位于響應包 Video[data][Component_Channel_Menu][list]躲雅,包含 media_id鼎姊、oid 和 mid
- 在博主的視頻頁(https://weibo.com/u/xxx?tabtype=newVideo)
默認視頻有 20 個,同樣的相赁,如果往下刷新相寇,響應包頁會繼續(xù)更新
每個視頻對應的網(wǎng)址位于響應包 [list][data][num(視頻列表)][url_struct][0][actionlog][oid],包含 oid
- 不同的視頻類型
只有明星的視頻下載網(wǎng)址才是 m3u8钮科,普通用戶或大 V 的視頻下載網(wǎng)址是 mp4
理論上前者的視頻格式播放速度是遠快于后者唤衫,且占用資源更多(原因自行百度),緣由應該是粉絲訪問基數(shù)太大
"""
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 已經(jīng)用完, 即將更新!") # for 循環(huán)結束绵脯,繼續(xù)提取新 ip
else:
print("獲取代理 ip 出現(xiàn)異常佳励,重新獲取!")
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份帐,充分的說明了該程序員的開發(fā)能力不足
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()
image.png
爬取電影 emmm
實現(xiàn)自動化登入極驗 / B 站 / 12306(繞過驗證碼)
推薦好文:利用selenium攜帶cookies實現(xiàn)免登錄【可實現(xiàn) selenium + cookies 的效果】
"""
實現(xiàn)自動化登入極驗(Requests + 識別圖片)
"""
"""
實現(xiàn)自動化登入 B 站(Selenium + 識別圖片)
"""
"""
實現(xiàn)自動化登入 12306(Selenium + 拖動滑塊)
"""