Blogger Information
Blog 9
fans 0
comment 0
visits 7046
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
利用Python获取某游戏网站热销商品并用pands进行Excel数据存储
IPIDEA全球HTTP
Original
548 people have browsed it

由于审核原因,本文中的网站以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):  
2.        url = 'https://那个网站/search/results/?query&start=0&count=50&sort_by=_ASC&os=win&snr=1_7_7_globaltopsellers_7&filter=globaltopsellers&infinite=1'  
3.        res = self.getRes(url,self.headers,'','','GET')#自己封装的请求方法  
4.        res = res.json()['results_html']  
5.        sel = Selector(text=res)  
6.        nodes = sel.css('.search_result_row')  
7.        for node in nodes:  
8.            gamedata = {}  
9.            gamedata['url'] = node.css('a::attr(href)').extract_first()#链接  
10.            gamedata['name'] = node.css('a .search_name .title::text').extract_first()#游戏名  
11.            gamedata['sales_date'] = node.css('a .search_released::text').extract_first()#发售日  
12.            discount = node.css('.search_discount span::text').extract_first()#是否打折  
13.            gamedata['discount'] = discount if discount else 'no discount'  
14.            price = node.css('a .search_price::text').extract_first().strip()#价格  
15.            discountPrice = node.css('.discounted::text').extract()#打折后的价格  
16.            discountPrice = discountPrice[-1] if discountPrice else ''  
17.            gamedata['price'] = discountPrice if discountPrice else price#最终价格  
18.            print(gamedata)

 1665382379519090.png

二、pandas保存数据 

2.1 构建pandas DataFrame对象

pandas存储Excel数据利用的是pandas对象的to_excel方法,将pandas的Dataframe对象直接插入Excel表中。

而DataFrame表示的是矩阵的数据表,包含已排序的列集合。

首先,先将获取到的数据,构建成Dataframe对象,先将我们获取的数据分别存入对应的list中,获取的url存到url的list,游戏名存到name的list:

1. url = []  
2. name = []  
3. sales_date = []  
4. discount = []  
5. price = []

 

1. url = node.css('a::attr(href)').extract_first()  
2. if url not in self.url:  
3.     self.url.append(url)  
4.     name = node.css('a .search_name .title::text').extract_first()  
5.     sales_date = node.css('a .search_released::text').extract_first()  
6.     discount = node.css('.search_discount span::text').extract_first()  
7.     discount = discount if discount else 'no discount'  
8.     price = node.css('a .search_price::text').extract_first().strip()  
9.     discountPrice = node.css('.discounted::text').extract()  
10.     discountPrice = discountPrice[-1] if discountPrice else ''  
11.     price = discountPrice if discountPrice else price  
12.     self.name.append(name)  
13.     self.sales_date.append(sales_date)  
14.     self.discount.append(discount)  
15.     self.price.append(price)  
16. else:  
17.     print('已存在')

将list组成相应的字典

1. data = {  
2.             'URL':self.url,'游戏名':self.name,'发售日':self.sales_date,'是否打折':self.discount,'价格':self.price  
3.         }  
其中dict中的key值对应的是Excel的列名。之后用pandas的DataFrame()方法构建对象,之后插入Excel文件。
1. data = {  
2.             'URL':self.url,'游戏名':self.name,'发售日':self.sales_date,'是否打折':self.discount,'价格':self.price  
3.         }  
4. frame = pd.DataFrame(data)  
5. xlsxFrame = pd.read_excel('./steam.xlsx')

其中pd是引入pandas包的对象,约定俗成的见到pd就是引入了pandas。

import pandas as pd

2.2 pandas追加插入Excel

如果要是翻页的话,重复调用插入Excel方法时你会发现Excel表内的数据并不会增多,因为每一次to_excel()方法都会把你上一次写入的数据覆盖掉。

所以若想保留之前写入的数据,那就先把之前写入的数据读出来,然后和新产生的数据进行DaraFrame对象的合并,将总的数据再次写入Excel

frame = frame.append(xlsxFrame)

 写入方法如下:

1. def insert_info(self):  
2.     data = {  
3.         'URL':self.url,'游戏名':self.name,'发售日':self.sales_date,'是否打折':self.discount,'价格':self.price  
4.     }  
5.     frame = pd.DataFrame(data)  
6.     xlsxFrame = pd.read_excel('./steam.xlsx')  
7.     print(xlsxFrame)  
8.     if xlsxFrame is not None:  
9.         print('追加')  
10.         frame = frame.append(xlsxFrame)  
11.         frame.to_excel('./steam.xlsx', index=False)  
12.     else:  
13.         frame.to_excel('./steam.xlsx', index=False)

逻辑:

1.将已有的数据生成DataFrame

2.读取之前写入的Excel文件,判断是否写入过数据

3.如果写入,将数据读出来合并后再次写入Excel

4.如果源文件为空,直接写入即可

三、代码整合

1. import requests  
2. from scrapy import Selector  
3. import pandas as pd  
4.    
5. class getSteamInfo():  
6.    
7.     headers = {  
8.         "Host": "那个网站",  
9.         "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",  
10.         "accept-encoding": "gzip, deflate, br",  
11.         "accept-language": "zh-CN,zh;q=0.9",  
12.         "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",  
13.     }  
14.    
15.     url = []  
16.     name = []  
17.     sales_date = []  
18.     discount = []  
19.     price = []  
20.    
21.     # api获取ip  
22.     def getApiIp(self):  
23.         # 获取且仅获取一个ip  
24.         api_url = 'api地址'  
25.         res = requests.get(api_url, timeout=5)  
26.         try:  
27.             if res.status_code == 200:  
28.                 api_data = res.json()['data'][0]  
29.                 proxies = {  
30.                     'http': 'http://{}:{}'.format(api_data['ip'], api_data['port']),  
31.                     'https': 'http://{}:{}'.format(api_data['ip'], api_data['port']),  
32.                 }  
33.                 print(proxies)  
34.                 return proxies  
35.             else:  
36.                 print('获取失败')  
37.         except:  
38.             print('获取失败')  
39.    
40.     def getInfo(self):  
41.         url = 'https://那个网站/search/results/?query&start=0&count=50&sort_by=_ASC&os=win&snr=1_7_7_globaltopsellers_7&filter=globaltopsellers&infinite=1'  
42.         res = self.getRes(url,self.headers,'','','GET')#自己封装的请求方法  
43.         res = res.json()['results_html']  
44.         sel = Selector(text=res)  
45.         nodes = sel.css('.search_result_row')  
46.         for node in nodes:  
47.             url = node.css('a::attr(href)').extract_first()  
48.             if url not in self.url:  
49.                 self.url.append(url)  
50.                 name = node.css('a .search_name .title::text').extract_first()  
51.                 sales_date = node.css('a .search_released::text').extract_first()  
52.                 discount = node.css('.search_discount span::text').extract_first()  
53.                 discount = discount if discount else 'no discount'  
54.                 price = node.css('a .search_price::text').extract_first().strip()  
55.                 discountPrice = node.css('.discounted::text').extract()  
56.                 discountPrice = discountPrice[-1] if discountPrice else ''  
57.                 price = discountPrice if discountPrice else price  
58.                 self.name.append(name)  
59.                 self.sales_date.append(sales_date)  
60.                 self.discount.append(discount)  
61.                 self.price.append(price)  
62.             else:  
63.                 print('已存在')  
64.         # self.insert_info()  
65.    
66.     def insert_info(self):  
67.         data = {  
68.             'URL':self.url,'游戏名':self.name,'发售日':self.sales_date,'是否打折':self.discount,'价格':self.price  
69.         }  
70.         frame = pd.DataFrame(data)  
71.         xlsxFrame = pd.read_excel('./steam.xlsx')  
72.         print(xlsxFrame)  
73.         if xlsxFrame is not None:  
74.             print('追加')  
75.             frame = frame.append(xlsxFrame)  
76.             frame.to_excel('./steam.xlsx', index=False)  
77.         else:  
78.             frame.to_excel('./steam.xlsx', index=False)  
79.    
80.     # 专门发送请求的方法,代理请求三次,三次失败返回错误  
81.     def getRes(self,url, headers, proxies, post_data, method):  
82.         if proxies:  
83.             for i in range(3):  
84.                 try:  
85.                     # 传代理的post请求  
86.                     if method == 'POST':  
87.                         res = requests.post(url, headers=headers, data=post_data, proxies=proxies)  
88.                     # 传代理的get请求  
89.                     else:  
90.                         res = requests.get(url, headers=headers, proxies=proxies)  
91.                     if res:  
92.                         return res  
93.                 except:  
94.                     print(f'第{i+1}次请求出错')  
95.                 else:  
96.                     return None  
97.         else:  
98.             for i in range(3):  
99.                 proxies = self.getApiIp()  
100.                 try:  
101.                     # 请求代理的post请求  
102.                     if method == 'POST':  
103.                         res = requests.post(url, headers=headers, data=post_data, proxies=proxies)  
104.                     # 请求代理的get请求  
105.                     else:  
106.                         res = requests.get(url, headers=headers, proxies=proxies)  
107.                     if res:  
108.                         return res  
109.                 except:  
110.                     print(f"第{i+1}次请求出错")  
111.                 else:  
112.                     return None  
113.    
114. if __name__ == '__main__':  
115.     getSteamInfo().getInfo()

对了,本次数据是获取的美服数据哦。最近国内访问不稳定,若是想要获取数据不买游戏的话建议使用代理进行访问。我这里使用的是ipidea的代理,新用户可以白嫖流量哦。

地址:http://www.ipidea.net/

最后奉劝大家:适当游戏,理智消费 ,认真生活,支持正版。(大批量的数据还是存数据库吧,人家也支持导出Excel)

 


Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post