因为要求,这个不知名的网站用S代替了。
有刚刚使用S的用户,不知道玩什么游戏怎么办?往往热销商品会使他们最合适的选择。
当然,某个第三方的网站上面的数据会更详细,什么游戏用户活跃度高,哪个区服游戏价格更便宜上面都会有。但是加上了一层Cloudflare的浏览器验证。
有人说用cloudscraper,但是cloudscraper对商用版的Cloudflare好像不管用(应该是吧,如果有大佬有更好的方法请及时指出,谢谢),之后会用其他的方法再试试。所以这边先按下不表,开始获取S的热销信息。
点击进入热销商品页:
https://那个网站/search/?sort_by=_ASC&force_infinite=1&snr=1_7_7_globaltopsellers_7&filter=globaltopsellers&page=2&os=win
上面的链接,仅仅能获取第一页的数据。
通过开发者模式找到真正的内容获取链接是:
https://那个网站/search/results/?query&start=0&count=50&sort_by=_ASC&os=win&snr=1_7_7_globaltopsellers_7&filter=globaltopsellers&infinite=1
其中start对应了开始位置,对应了翻页。count对应了一次获取了多少数据。
get请求即可,上代码:
def getInfo(self):
url = 'https://那个网站/search/results/?query&start=0&count=50&sort_by=_ASC&os=win&snr=1_7_7_globaltopsellers_7&filter=globaltopsellers&infinite=1'
res = self.getRes(url,self.headers,'','','GET')#自己封装的请求方法
res = res.json()['results_html']
sel = Selector(text=res)
nodes = sel.css('.search_result_row')
for node in nodes:
gamedata = {}
gamedata['url'] = node.css('a::attr(href)').extract_first()#链接
gamedata['name'] = node.css('a .search_name .title::text').extract_first()#游戏名
gamedata['sales_date'] = node.css('a .search_released::text').extract_first()#发售日
discount = node.css('.search_discount span::text').extract_first()#是否打折
gamedata['discount'] = discount if discount else 'no discount'
price = node.css('a .search_price::text').extract_first().strip()#价格
discountPrice = node.css('.discounted::text').extract()#打折后的价格
discountPrice = discountPrice[-1] if discountPrice else ''
gamedata['price'] = discountPrice if discountPrice else price#最终价格
print(gamedata)
pandas存储Excel数据利用的是pandas对象的to_excel方法,将pandas的Dataframe对象直接插入Excel表中。
而DataFrame表示的是矩阵的数据表,包含已排序的列集合。
首先,先将获取到的数据,构建成Dataframe对象,先将我们获取的数据分别存入对应的list中,获取的url存到url的list,游戏名存到name的list:
url = []
name = []
sales_date = []
discount = []
price = []
url = node.css('a::attr(href)').extract_first()
if url not in self.url:
self.url.append(url)
name = node.css('a .search_name .title::text').extract_first()
sales_date = node.css('a .search_released::text').extract_first()
discount = node.css('.search_discount span::text').extract_first()
discount = discount if discount else 'no discount'
price = node.css('a .search_price::text').extract_first().strip()
discountPrice = node.css('.discounted::text').extract()
discountPrice = discountPrice[-1] if discountPrice else ''
price = discountPrice if discountPrice else price
self.name.append(name)
self.sales_date.append(sales_date)
self.discount.append(discount)
self.price.append(price)
else:
print('已存在')
将list组成相应的字典
data = {
'URL':self.url,'游戏名':self.name,'发售日':self.sales_date,'是否打折':self.discount,'价格':self.price
}
其中dict中的key值对应的是Excel的列名。之后用pandas的DataFrame()方法构建对象,之后插入Excel文件。
data = {
'URL':self.url,'游戏名':self.name,'发售日':self.sales_date,'是否打折':self.discount,'价格':self.price
}
frame = pd.DataFrame(data)
xlsxFrame = pd.read_excel('./steam.xlsx')
其中pd是引入pandas包的对象,约定俗成的见到pd就是引入了pandas。
import pandas as pd
如果要是翻页的话,重复调用插入Excel方法时你会发现Excel表内的数据并不会增多,因为每一次to_excel()方法都会把你上一次写入的数据覆盖掉。
所以若想保留之前写入的数据,那就先把之前写入的数据读出来,然后和新产生的数据进行DaraFrame对象的合并,将总的数据再次写入Excel
frame = frame.append(xlsxFrame)
写入方法如下:
def insert_info(self):
data = {
'URL':self.url,'游戏名':self.name,'发售日':self.sales_date,'是否打折':self.discount,'价格':self.price
}
frame = pd.DataFrame(data)
xlsxFrame = pd.read_excel('./steam.xlsx')
print(xlsxFrame)
if xlsxFrame is not None:
print('追加')
frame = frame.append(xlsxFrame)
frame.to_excel('./steam.xlsx', index=False)
else:
frame.to_excel('./steam.xlsx', index=False)
逻辑:
import requests
from scrapy import Selector
import pandas as pd
class getSteamInfo():
headers = {
"Host": "那个网站",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"accept-encoding": "gzip, deflate, br",
"accept-language": "zh-CN,zh;q=0.9",
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.82 Safari/537.36",
}
url = []
name = []
sales_date = []
discount = []
price = []
# api获取ip
def getApiIp(self):
# 获取且仅获取一个ip
api_url = 'api地址'
res = requests.get(api_url, timeout=5)
try:
if res.status_code == 200:
api_data = res.json()['data'][0]
proxies = {
'http': 'http://{}:{}'.format(api_data['ip'], api_data['port']),
'https': 'http://{}:{}'.format(api_data['ip'], api_data['port']),
}
print(proxies)
return proxies
else:
print('获取失败')
except:
print('获取失败')
def getInfo(self):
url = 'https://那个网站/search/results/?query&start=0&count=50&sort_by=_ASC&os=win&snr=1_7_7_globaltopsellers_7&filter=globaltopsellers&infinite=1'
res = self.getRes(url,self.headers,'','','GET')#自己封装的请求方法
res = res.json()['results_html']
sel = Selector(text=res)
nodes = sel.css('.search_result_row')
for node in nodes:
url = node.css('a::attr(href)').extract_first()
if url not in self.url:
self.url.append(url)
name = node.css('a .search_name .title::text').extract_first()
sales_date = node.css('a .search_released::text').extract_first()
discount = node.css('.search_discount span::text').extract_first()
discount = discount if discount else 'no discount'
price = node.css('a .search_price::text').extract_first().strip()
discountPrice = node.css('.discounted::text').extract()
discountPrice = discountPrice[-1] if discountPrice else ''
price = discountPrice if discountPrice else price
self.name.append(name)
self.sales_date.append(sales_date)
self.discount.append(discount)
self.price.append(price)
else:
print('已存在')
# self.insert_info()
def insert_info(self):
data = {
'URL':self.url,'游戏名':self.name,'发售日':self.sales_date,'是否打折':self.discount,'价格':self.price
}
frame = pd.DataFrame(data)
xlsxFrame = pd.read_excel('./steam.xlsx')
print(xlsxFrame)
if xlsxFrame is not None:
print('追加')
frame = frame.append(xlsxFrame)
frame.to_excel('./steam.xlsx', index=False)
else:
frame.to_excel('./steam.xlsx', index=False)
# 专门发送请求的方法,代理请求三次,三次失败返回错误
def getRes(self,url, headers, proxies, post_data, method):
if proxies:
for i in range(3):
try:
# 传代理的post请求
if method == 'POST':
res = requests.post(url, headers=headers, data=post_data, proxies=proxies)
# 传代理的get请求
else:
res = requests.get(url, headers=headers, proxies=proxies)
if res:
return res
except:
print(f'第{i+1}次请求出错')
else:
return None
else:
for i in range(3):
proxies = self.getApiIp()
try:
# 请求代理的post请求
if method == 'POST':
res = requests.post(url, headers=headers, data=post_data, proxies=proxies)
# 请求代理的get请求
else:
res = requests.get(url, headers=headers, proxies=proxies)
if res:
return res
except:
print(f"第{i+1}次请求出错")
else:
return None
if __name__ == '__main__':
getSteamInfo().getInfo()
对了,本次数据是获取的美服数据哦。最近国内访问不稳定,若是想要获取数据不买游戏的话建议使用代理进行访问。我这里使用的时ipidea的代理,新用户可以白嫖流量哦。
地址:http://www.ipidea.net/?utm-source=csdn&utm-keyword=?wb
最后奉劝大家:适当游戏,理智消费 ,认真生活,支持正版。(大批量的数据还是存数据库吧,人家也支持导出Excel)