乐趣区

关于前端:利用Python获取某游戏网站热销商品并用pands进行Excel数据存储

因为审核起因,本文中的网站以 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 申请即可,上代码:

1.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)  

二、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:  
    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)

退出移动版