import random
import re
import time
import xlsxwriter
from selenium import webdriver
from lxml import etree
import requests
# ua池
ua_list=[
"Mozilla/5.0 (Windows NT 10.0; Win64; x32) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.39 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.26 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36",
'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36',
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X; zh-CN) AppleWebKit/537.51.1 (KHTML, like Gecko) Mobile/17D50 UCBrowser/12.8.2.1268 Mobile AliApp(TUnionSDK/0.1.20.3)',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36',
'Mozilla/5.0 (Linux; Android 8.1.0; OPPO R11t Build/OPM1.171019.011; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/76.0.3809.89 Mobile Safari/537.36 T7/11.19 SP-engine/2.15.0 baiduboxapp/11.19.5.10 (Baidu; P1 8.1.0)',
'Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36',
'Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.14.0 main%2F1.0 baiduboxapp/11.18.0.16 (Baidu; P2 13.3.1) NABar/0.0',
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.17134',
'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
]
ua=random.choice(ua_list)
# Ip池
proxy_list=[
{"http" or "https": "124.71.14.222:10002"},
{"http" or "https": '60.167.133.17:1133'},
{"http" or "https": '183.0.203.167:8118'},
{"http" or "https": '111.231.86.149:7890'},
{"http" or "https": "183.0.203.167:8118"},
{"http" or "https": '163.125.222.12:8118'},
{"http" or "https": '111.59.199.58:8118'},
]
proxies=random.choice(proxy_list)
word=input('请输入你要获取的商品:', )
page=input('请输入商品页数:',)
# 获取商品链接和id
def get_link():
links=[]
skus_id=[]
for i in range(int(page)):
url=f'https://search.jd.com/Search?keyword={word}&wq={word}&page={i}'
headers={
"user-agent": ua,
}
res=requests.get(url=url, headers=headers, proxies=proxies).text
time.sleep(0.5)
# print(res)
# 提取商品链接并进行拼接操作
html=etree.HTML(res)
link=html.xpath('//*[@id="J_goodsList"]/ul/li[*]/div/div[3]/a/@href')
link=['https:' + k for k in link]
for l in link:
links.append(l)
# 提取商品id
sku_id=[re.findall('\d+', i)[0] for i in link]
for s in sku_id:
skus_id.append(s)
print(f'第{i+1}页。')
print(links)
goods(links, skus_id)
# 获取商品详情
def goods(links, skus_id):
goo=[]
pict=0
for i in range(len(links)):
headers={
"User-Agent": ua,
'referer': 'https://search.jd.com/',
}
res=requests.get(url=links[i], headers=headers, proxies=proxies).text
time.sleep(2)
# print(res)
html=etree.HTML(res)
# 店铺名称
title=html.xpath('//*[@id="crumb-wrap"]/div/div[2]/div[2]/div[1]/div/a/@title')
print(title)
# 品牌
brand=html.xpath('//*[@id="parameter-brand"]/li/@title')
print(brand)
# 商品编号
serial=html.xpath('//*[@id="detail"]/div[2]/div[1]/div[1]/ul[2]/li[2]/text()')
serial=[serial[0].split(':')[-1]]
print(serial)
# 正式商品名称
official=html.xpath('//*[@id="detail"]/div[2]/div[1]/div[1]/ul[2]/li[1]/text()')
official=[official[0].split(':')[-1].strip()]
print(official)
# 网页商品名称
name=html.xpath('/html/body/div[6]/div/div[2]/div[1]/text()')
if len(name)==1:
name=[name[0].strip()]
elif len(name)==2:
name=[name[1].strip()]
print(name)
# 商品第一张主图片
picture=['https:' + html.xpath('//*[@id="spec-img"]/@data-origin')[0]]
print(picture)
res2=requests.get(url=picture[0], headers=headers)
with open(f'D:\pythonproject\python项目爬虫\接单\京东商品评价获取(接单考核)\商品图片/{pict}.jpg', 'wb')as f:
f.write(res2.content)
pict +=1
# 京东价,请求价格信息json
p=requests.get('https://p.3.cn/prices/mgets?skuIds=J_' + skus_id[i], headers=headers, proxies=proxies).text
print(p)
price=re.findall('"p":"(.*?)","op"', p)
print(price)
# 优惠劵和促销
options=webdriver.ChromeOptions()# 无界面模式
options.add_argument('--headless')
driver=webdriver.Chrome(options=options)
driver.get(links[i])
time.sleep(1)
# 获取源代码
data=driver.page_source
time.sleep(0.5)
driver.close()
driver.quit()
# 促销
html2=etree.HTML(data)
promotion1=html2.xpath('//*[@id="prom"]/div/div[1]/em[2]/text()')
promotion2=html2.xpath('//*[@id="prom"]/div/div[2]/em[2]/text()')
if promotion1==[] and promotion2==[]:
promotion=['暂无促销信息']
elif promotion1==[] and promotion2 !=[]:
promotion=promotion2
elif promotion2==[] and promotion1 !=[]:
promotion=promotion1
else:
promotion=[promotion1[0], promotion2[0]]
print(promotion)
# 优惠劵信息
coupon=html2.xpath('//*[@id="summary-quan"]/div[2]/dl/dd/a/span/span/text()')
if coupon==[]:
coupon=['暂无可领的优惠券']
print(coupon)
# 累计评价
comm_url=f'https://club.jd.com/comment/productCommentSummaries.action?referenceIds={skus_id[i]}'
comment_headers={
'user-agent': ua,
}
res_js=requests.get(url=comm_url, headers=comment_headers, proxies=proxies).text
comment=re.findall('"CommentCountStr":"(.*?)","CommentCount":', res_js)
print(comment)
for g in zip(title, brand, serial, official, name, price, promotion, coupon, comment, picture):
goo.append(g)
print(f'第{i+1}件商品打印完成。')
print(goo)
save(goo)
5.数据保存,并通过xlsxwrite进行图片保存
# 数据保存
def save(goo):
# 创建工作簿
workbook=xlsxwriter.Workbook('京东商品详情.xlsx')
# 创建工作表
worksheet=workbook.add_worksheet(word)
# 大部分样式如下:
format={
# 'font_size': 10, # 字体大小
'bold': True, # 是否粗体
# 'bg_color': '#101010', # 表格背景颜色
# 'fg_color': '#00FF00',
# 'font_color': '#0000FF', # 字体颜色
'align': 'center', # 水平居中对齐
'valign': 'vcenter', # 垂直居中对齐
# 'num_format': 'yyyy-mm-dd H:M:S',# 设置日期格式
# 后面参数是线条宽度
'border': 1, # 边框宽度
'top': 1, # 上边框
'left': 1, # 左边框
'right': 1, # 右边框
'bottom': 1 # 底边框
}
style=workbook.add_format(format)
# 写入图片
a=0
worksheet.set_column(9, 9, 350) # 设置列宽
for i in range(len(goo)):
worksheet.set_row(i + 1, 350) # 设置行高350
worksheet.insert_image(i + 1, 9, f'D:\pythonproject\python项目爬虫\接单\京东商品评价获取(接单考核)\商品图片/{a}.jpg', {'url': goo[i][-1]})
a +=1
# 写入数据
col=('店铺名称', '品牌', '商品编号', '正式商品名称', '网页商品名称', '京东价', '促销', '优惠劵', '累计评价', '商品第一张主图片',)
for i in range(len(col)):
worksheet.write(0, i, col[i])
for i in range(len(goo)):
for c in range(len(col) - 1):
worksheet.write(i + 1, c, goo[i][c], style)
workbook.close()
6.开启程序
if __name__=='__main__':
get_link()
原文链接:https://blog.csdn.net/weixin_62871152/article/details/121457846
开始之前,做一点小小的说明哈:
首先打开网易云的网页版网易云
然后搜索歌曲,这里我就搜索一首锦零的“空山新雨后”
这时我们来观察网页的url,可以发现s=后面就是我们搜索的关键字
当我们换一首歌,会发现也是这样的,正好验证了我们的想法
所以下一步让我们点进去一首歌,然后进行播放,看看能否直接获取音乐文件的url,如果能,那么直接对url进行requests.get访问,我们就能拿到.mp3文件了
点进第一首“空山新雨后”,我们可以看到有一个“生成外链播放器”
看到这个,我心中一阵激动,仿佛就要大功告成;于是我满怀开心的点了一下,结果。。。
好吧,不过我们不能放弃,来我们分析一下网页
但当我们定位到两个最有可能出现外链的地方时,发现什么都没有
不过作为“规格严格,功夫到家”的传承者,我不能放弃啊,于是我又打开了抓包工具
按照常规套路,我们定位到XHR
点击播放后,出现了一大堆东西,我们要做的就是找到其中的content-type为audio一类的包
功夫不负有心人,在寻找了一(亿)会儿后,我找到了
于是我又满怀开心的复制了这个包对应的Request-URL
粘贴后访问这个url,结果非常满意,这就是我一直在找的url
现在我把那个url贴出来
https://m10.music.126.net/20200715163315/a075d787d191f6729a517527d6064f59/ymusic/0552/0f0e/530f/28d03e94478dcc3e0479de4b61d224e9.mp3
接下来就超级简单了
下面的代码是最常规的操作,应该有爬虫基础的都能看懂;如果有不懂的,注释都在上面
#导入requests包
import requests
#进行UA伪装
headers={
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.116 Safari/537.36'
}
#指定url
url='https://m10.music.126.net/20200715163315/a075d787d191f6729a517527d6064f59/ymusic/0552/0f0e/530f/28d03e94478dcc3e0479de4b61d224e9.mp3'
#调用requests.get方法对url进行访问,和持久化存储数据
audio_content=requests.get(url=url,headers=headers).content
#存入本地
with open('空山新雨后.mp3','wb') as f :
f.write(audio_content)
print("空山新雨后爬取成功!!!")
看到这里,你可能会想,为啥根本没用selenium模块呢?能不能直接爬取任何一首我想要的歌,而不用每首都去费心费力的找一个url呢?当然可以哒!
其实网易云在线播放每首歌曲时,都有一个外链地址,这是不会变的,跟每首歌的唯一一个id绑定在一起,每首歌audio文件的url如下:
url='http://music.163.com/song/media/outer/url?id=' + 歌曲的id值 + '.mp3'
id值的获取也很简单,当我们点进每首歌时,上方会出现对应的网址,那里有id值,如下图:
所以只需把上面程序中的url改成新的url即可
如果还想要更好的体验效果,实现在程序里直接搜索歌曲,拿到id值,就需要用到selenium模块
为什么用selenium而不用xpath或bs4?
因为搜索页面的数据是动态加载出来的,如果直接对搜索页面的网页进行数据解析,就拿不到任何数据;以我目前的技术,就只能想到使用万能的selenium模块,下面大概说明一下步骤:
from selenium.webdriver.chrome.options import Options
chrome_options=Options()
chrome_options.add_argument('--headless')
chrome_options.add_argument('--disable-gpu')
import requests
import re
from selenium import webdriver
from time import sleep
name=input('请输入歌名:')
url_1='https://music.163.com/#/search/m/?s=' + name + '&type=1'
#初始化browser对象
browser=webdriver.Chrome(executable_path='chromedriver.exe',chrome_options=chrome_options)
#访问该url
browser.get(url=url_1)
#由于网页中有iframe框架,进行切换
browser.switch_to.frame('g_iframe')
#等待0.5秒
sleep(0.5)
#抓取到页面信息
page_text=browser.execute_script("return document.documentElement.outerHTML")
#退出浏览器
browser.quit()
ex1='<a.*?id="([0-9]*?)"'
ex2='<b.*?title="(.*?)"><span class="s-fc7">'
ex3='class="td w1"><div.*?class="text"><a.*?href=".*?">(.*?)</a></div></div>'
id_list=re.findall(ex1,page_text,re.M)[::2]
song_list=re.findall(ex2,page_text,re.M)
singer_list=re.findall(ex3,page_text,re.M)
li=list(zip(song_list,singer_list,id_list))
for i in range(len(li)):
print(str(i+1) + '.' + str(li[i]),end='\n')
终究是我才疏学浅,这个找外链进行爬取的方法也存在很多不足,比如不能在线播放的歌曲是无法下载的。
不过写这样一个小程序练练手,对自己能力的提高确是有极大帮助的。
Python 和 JavaScript 是两种广泛应用于 Web 开发的重要编程语言,在日常的 Web 开发和 Web 数据处理中,我们经常需要使用这两种语言。
例如,在 Web 端爬虫过程中,我们可能会遇到需要解密网页源代码的情况,这时就需要一层一层剥离关键的 JS 代码,并使用 Python 执行这段代码以获取关键信息。
那么,Python 如何调用 JS 呢?有哪些方式呢?
以一段简单的JS脚本(add.js)为例,计算两个数的和。
// JavaScript 示例代码
function add(a, b) {
return a + b;
}
使用 Python 的os.popen或subprocess执行 node 命令,执行 JS 脚本。
首先,确保本地已经安装了 Node.js 环境:
> node -v
v18.16.1
修改 JS 脚本,新增一个导出函数 init ,方便内部函数被调用:
// JavaScript 示例代码
function add(a, b) {
return a + b;
}
// 新增一个导出函数(node方式)
module.exports.init=function (arg1, arg2) {
// 调用函数,并返回
console.log(add(arg1, arg2));
};
// 调用 init 方法并传递参数
module.exports.init(parseInt(process.argv[3]), parseInt(process.argv[4]));
使用subprocess模拟node.js命令行调用并获取结果:
import subprocess
from loguru import logger
if __name__=='__main__':
# 使用 subprocess 模块执行 Node.js 命令
result=subprocess.run(["node", "add.js", "init", "3", "5"], capture_output=True, text=True)
# 输出执行结果
logger.info(f"Node.js 执行结果: {result.stdout.strip()}")
PyExecJS 是使用最多的一种方式,底层实现方式是本地 JS 环境下运行 JS 代码,支持的 JS 环境包含:Node.js、PhantomJS 等。
首先第一步安装:
pip install PyExecJS==1.5.1
安装完成之后,即可以使用其调用 JS 脚本:
#! -*-conding=: UTF-8 -*-
from loguru import logger
import execjs
# 定义 JavaScript 代码
# js_code="""
# function add(a, b) {
# return a + b;
# }
# """
if __name__=='__main__':
# Python 示例代码
js_code=open("add.js", "r", encoding="utf-8").read()
# 使用 PyExecJS 执行 JavaScript 代码
ctx=execjs.compile(js_code)
# 调用 JavaScript 函数,并计算结果
result=ctx.call("add", 3, 5)
logger.info(f"调用 JavaScript 函数的结果为: {result}")
DrissionPage方式
这款工具既能控制浏览器,也能收发数据包,甚至能把两者合而为一。
首先安装依赖库:
pip install DrissionPage==4.0.4.22
执行 JS 脚本:
#! -*-conding=: UTF-8 -*-
from DrissionPage import ChromiumPage
if __name__=='__main__':
page=ChromiumPage()
# 打开网页
page.get("about:blank")
# 定义 JavaScript 代码
js_code="""
function add(a, b) {
return a + b;
}
"""
# 在当前页面上执行 JavaScript 代码,并传递参数
result=page.run_js(js_code + " return add(8, 5)")
# 输出执行结果
print("JavaScript 执行结果:", result) # JavaScript 执行结果: 13
page.quit()
playwright方式
Playwright 是一个用于 Web 测试和自动化的框架。
首先安装依赖库:
pip install playwright==1.43.0
playwright install # 安装驱动
执行 JS 脚本:
#! -*-conding=: UTF-8 -*-
from playwright.sync_api import sync_playwright
if __name__=='__main__':
# 启动 Playwright
with sync_playwright() as p:
# 启动 Chromium 浏览器
browser=p.chromium.launch(headless=False)
# 创建新页面
page=browser.new_page()
# 打开网页
page.goto("https://baidu.com")
# 定义 JavaScript 代码
js_code="""
function add(a, b) {
return a + b;
}
"""
page.add_script_tag(content=js_code) # 使用 page.add_script_tag() 方法将其注入到页面中,然后在页面上执行它
# 在当前页面上执行 JavaScript 代码
result=page.evaluate("add(5, 7)")
# 输出执行结果
print("JavaScript 执行结果:", result) # JavaScript 执行结果: 12
# 关闭浏览器
browser.close()
selenium方式
Selenium是一个用于测试网站的自动化测试工具,支持各种浏览器包括 Chrome、Firefox、Safari 等主流界面浏览器和 phantomJS 无界面浏览器。
首先安装依赖库:
pip install selenium==4.20.0
执行 JS 脚本:
#! -*-conding=: UTF-8 -*-
from selenium import webdriver
# 启动 Chrome 浏览器
driver=webdriver.Chrome()
# 打开网页
driver.get("about:blank")
# 定义 JavaScript 代码
js_code="""
function add(a, b) {
return a + b;
}
"""
# 在当前页面上执行 JavaScript 代码,并传递参数
result=driver.execute_script(js_code + " return add(3, 5)")
# 输出执行结果
print("JavaScript 执行结果:", result)
# 关闭浏览器
driver.quit()
类似的自动化工具还有很多,如果只是单纯的调用 JS 脚本,属实有点杀鸡用牛刀的赶jio。
Js2Py 作为一个纯 Python 实现的 JS 解释器,可以完全脱离 JS 环境,直接将 JS 代码转换为 Python 代码。
首先第一步安装:
pip install Js2Py==0.74
调用 JS 脚本:
#! -*-conding=: UTF-8 -*-
from js2py import eval_js
if __name__=='__main__':
# JavaScript 示例代码
js_code="""
function add(a, b) {
return a + b;
}
"""
# 执行 JavaScript 代码
result=eval_js(js_code + "add(3, 5)")
# 输出执行结果
print("JavaScript 执行结果:", result)
PyMiniRacer 是一个 Python 模块,它提供了一个轻量级、快速且安全的方式来执行 JavaScript 代码,无需借助完整的 V8 引擎或 Node.js 环境。
不知道佬们用的多不多,据说速度比PyExecJS快不少。
直接安装:
pip install py_mini_racer==0.6.0
运行:
#! -*-conding=: UTF-8 -*-
from py_mini_racer import MiniRacer
if __name__=='__main__':
# 创建 PyMiniRacer 实例
ctx=MiniRacer()
js_code="""
function add(a, b) {
return a + b;
}
"""
# 在 JavaScript 环境中执行代码并传递参数
ctx.eval(js_code)
result=ctx.call("add", 3, 5)
# 输出执行结果
print("JavaScript 执行结果:", result) # JavaScript 执行结果: 8
Python 中执行和调用 JavaScript 代码有多种方法:
每种工具都有其适用的场景和局限性,选择合适的工具取决于具体的需求和项目要求。
原文链接:https://juejin.cn/post/7367701663169790002
*请认真填写需求信息,我们会在24小时内与您取得联系。