logo资料库

淘宝、京东反反爬虫爬取手机信息.pdf

第1页 / 共14页
第2页 / 共14页
第3页 / 共14页
第4页 / 共14页
第5页 / 共14页
第6页 / 共14页
第7页 / 共14页
第8页 / 共14页
资料共14页,剩余部分请下载后查看
python 期末大作业 任务 1: 分别爬取京东和淘宝,在手机频道中,找出累积销量(所有商家销售同一型号手 机的销 量之和)最高的 20 款手机。 说明: 1) 销量:京东以评论数为准,淘宝以付款人 数为准。 2) 基础版本:一款手机只看最低配置和最低价格,例如 iPhone 11 只按照 64G 的价格来计 算。高级版本:一款手机有多个型号,不同的配置算不同的型号,例如 iPhone 11 64G 算是一种型号,128G 算另一种型号。按照自己的能力选做基础版本或者是高级版 本, 高级版本有加分。 结果展示: 按照销量,以直方图的形式展示手机型号及其销量, 按照销量倒排序。图中的手机型号 请尽量简化,能够区分即可。 一个 figure 中有 2 个子 图,2 个子图分别展示京东和淘宝中,手机价格直方图。 任务 2: 用你爬取下来的数据制作散点图,横轴为手机价格,纵轴为该价格对应的商家个 数。 结果展示: 一个 figure 中有 2 个子图,2 个子图分别展示京东和淘宝中,手机价格 的分布情况。 任务 3: 找出在两个平台上都有售卖的 5 款手机(找销量较大的) ,由于两个平台上都 有不同的 卖家都销售这些手机,价格也不同,需要将这些卖家销售这款手机的价格,做出 箱型图,比 较不同平台上的价格情况。 结果展示: 一个 figure 中有 5 个子图,每个子 图里面有两个平台上售卖的同一型号手机的 2 个价 格箱型图。 1.京东爬取代码: 采用 selenium+scrapy 方式爬取,爬取每一页时先将界面下拉,让其加载出全部 手机,因为京东是先加载出 30 个手机,需要往下拉才会动态加载出后面 30 个手 机,并且爬取每一个手机时,做到了点击进去,选择最低版本,然后爬取最低版 本的价格和手机型号。 import scrapy from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from Scripts.t2017211603.t2017211603.items import MyItem class mySpider(scrapy.spiders.Spider): name = "bupt" # 爬虫的名字是 bupt
allowed_domains = ["search.jd.com/"] # 允许爬取的网站域名 start_urls = ["https://search.jd.com/Search?keyword=%E6%89%8B%E6%9C%BA&enc=utf- 8&qrst=1&rt=1&stop=1&vt=2&wq" "=shou%27ji&psort=3&click=0"] item = MyItem() # 生成一个在 items.py 中定义好的 Myitem 对象,用于接收爬取的数 据 num = 1 # 设定爬取多少页 def __init__(self): chrome_options = webdriver.ChromeOptions() prefs = {"profile.managed_default_content_settings.images": 2} chrome_options.add_experimental_option("prefs", prefs) self.browser = webdriver.Chrome(chrome_options=chrome_options, executable_path=r"C:\Users\xingu\Desktop\chromedriver.exe") def start_requests(self): self.browser.implicitly_wait(30) self.browser.get(self.start_urls[0]) for url in self.start_urls: yield scrapy.Request(url=url, callback=self.parse) # 初始 URL,即爬虫爬取的第一个 URL def parse(self, response): # 解析爬取的内容 index = 1 print('------正在第',self.num,'页---') for each in response.xpath("/html/body/div[6]/div[2]/div[2]/div[1]/div/div[2]/ul/*"): # 用 xpath 来解析 html,div 标签中的数据,就是我们需要的数据 self.item['price'] = each.xpath("div/div[3]/strong/i/text()").extract()[0] self.item['num'] = each.xpath("div/div[5]/strong/a/text()").extract()[0] self.item['store'] = each.xpath("div/div[7]/span/a/text()").extract() self.item['url'] = each.xpath('div/div[1]/a/@href').extract() a = self.browser.find_element_by_xpath( "/html/body/div[6]/div[2]/div[2]/div[1]/div/div[2]/ul/li[" + str(index) + "]/div/div[1]/a") index += 1 self.browser.execute_script("arguments[0].click();", a) windows = self.browser.window_handles self.browser.switch_to.window(windows[1]) print("11111111") try:
= = WebDriverWait(self.browser, 1, 0.01).until( EC.presence_of_element_located((By.CSS_SELECTOR, 'ul.parameter2.p-parameter-list')) ) print("222222222") # //*[@id="detail"]/div[2]/div[1]/div[1]/ul[3]/li[1] self.item['name'] self.browser.find_element_by_css_selector("ul.parameter2.p-parameter-list > " "li:nth-child(1)").text try: if u'choose-attr-2' in self.browser.page_source: # 如果没有选择版本项就不用点击 path_price self.browser.find_element_by_xpath('//*[@id="choose-attr-2"]/div[2]/div[1]') path_price.click() print('click') self.item['price'] self.browser.find_element_by_css_selector('div.dd > span.p-price>' 'span:nth-child(2) ').text print("find the lowest price") else: print("无选择版本项") except: print('can\'t find price') print("3333333333") except: pass finally: self.browser.close() print("close!!!!!!") ##item-detail > div.p-parameter > ul > li:nth-child(1) #self.browser.close() #self.browser.switch_to.window(windows[0]) if self.item['price'] and self.item['num']: # 去掉值为空的数据 if not self.item['store']: self.item['store'] = '自营' else: self.item['store'] = self.item['store'][0] yield (self.item) # 返回 item 数据给到 pipelines 模块 if self.num < 100: =
= b self.browser.find_element_by_xpath("/html/body/div[6]/div[2]/div[2]/div[1]/div/div[3]/div/spa n[1]/a[9]") # /html/body/div[6]/div[2]/div[2]/div[1]/div/div[3]/div/span[1]/a[9] b.click() # time.sleep(2) url = self.browser.current_url yield scrapy.Request(url=url, callback=self.parse, dont_filter=True) self.num += 1 2.京东数据处理代码: import numpy as np import pandas as pd #1.打开 CSV 文件 file = 'mobilephone_jingdong.csv' df = pd.read_csv(file,encoding='utf-8') df = df.drop_duplicates(keep='first')# 只保存第一条重复数据 df['name']=df['name'].str.replace('商品名称:','') df['num']=df['num'].str.replace('+','') for index,row in df.iterrows(): print('---第',index,'行---',row['num']) if '万' in str(row['num']): row['num']=row['num'].replace('万','') row['num']=float(row['num'])*10000 print('hou:',row['num']) df['num'][index]=int(row['num']) df = df.drop(df[df.num<3000].index)#将销量太低的去掉 df=df.drop(df[df['name'].map(len) > 20].index)#将一些名称太长的无效数据去掉 print(df['name']) print(df['num']) df.to_csv("jingdong_result1.csv",encoding="utf-8") 3.淘宝数据的爬取: 应对反爬的方式:使用 selenium 模拟浏览器方式爬取,先通过以某个端口打 开 chrome 浏览器,手动登录淘宝,防止留下 selenium 指纹被淘宝封号:
再通过 9399 端口将浏览器控制,这样可以尽量不被淘宝检测到。先将手机价格, 付款人数,店名,店家的链接爬取出来,再通过访问链接得到手机的品牌和具体 型号。 爬取链接的代码: import scrapy from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from Scripts.test2.test2.items import MyItem import csv import time class mySpider(scrapy.spiders.Spider): name = "bupt" # 爬虫的名字是 bupt allowed_domains = ["s.taobao.com/"] # 允许爬取的网站域名 start_urls = ["https://s.taobao.com/search?q=%E6%89%8B%E6%9C%BA&imgfile=&commend=all&ssid=s5- e&search_type=item&" "sourceId=tb.index&spm=a21bo.2017.201856-taobao- item.1&ie=utf8&initiative_id=tbindexz_20170306"] item = MyItem() # 生成一个在 items.py 中定义好的 Myitem 对象,用于接收爬取的数 据 num = 1 # 设定爬取多少页 #chrome.exe --remote-debugging-port=9399 --user-data-dir="D:\test" def __init__(self):
['enable- chrome_options=webdriver.ChromeOptions() chrome_options.add_experimental_option('debuggerAddress', '127.0.0.1:9399') #chrome_options.add_experimental_option('excludeSwitches', automation']) self.browser = webdriver.Chrome(executable_path=r"C:\Users\xingu\Desktop\chromedriver.exe",chrome_o ptions=chrome_options) #executable_path="C:\\Users\\xingu\AppData\Local\Google\Chrome\Application\chrome_p roxy.exe" self.wait = WebDriverWait(self.browser, 10) def start_requests(self): self.browser.implicitly_wait(30) self.browser.get(self.start_urls[0]) self.browser.implicitly_wait(50) for url in self.start_urls: yield scrapy.Request(url=url, callback=self.parse) #yield scrapy.Request(url=self.browser.current_url, callback=self.parse) # 初始 URL,即爬虫爬取的第一个 URL def parse(self, response): # 解析爬取的内容 index = 1 print("ok") print('----正在获取第', self.num, '页----') for each in response.xpath('//*[@id="mainsrp-itemlist"]/div/div/div[1]/*'): # 用 xpath 来解析 html,div 标签中的数据,就是我们需要的数据 #//*[@id="mainsrp-itemlist"]/div/div/div[1]/div[1] #//*[@id="mainsrp-itemlist"]/div/div/div[1]/div[2]/div[2]/div[3]/div[1]/a url=each.xpath('div[1]/div/div[1]/a/@href').extract() self.item['num']=each.xpath('div[2]/div[1]/div[2]/text()').extract() self.item['price']=each.xpath('div[2]/div[1]/div[1]/strong/text()').extract() self.item['store'] = each.xpath('div[2]/div[3]/div[1]/a/span[2]/text()').extract() if not self.item['store']: self.item['store'] = each.xpath('div[2]/div[3]/div[1]/a/text()').extract() self.item['link']=url print(url) ##mainsrp-pager > div > div > div > div.form > span.btn.J_Submit yield (self.item) # 返回 item 数据给到 pipelines 模块 if self.num < 100: self.num += 1 input = self.wait.until( EC.presence_of_element_located((By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > input"))
) # 提交按钮 submit = self.wait.until( EC.element_to_be_clickable( (By.CSS_SELECTOR, "#mainsrp-pager > div > div > div > div.form > span.btn.J_Submit")) ) input.clear() input.send_keys(self.num) self.browser.execute_script("arguments[0].click();", submit) time.sleep(1) print('click') yield dont_filter=True) scrapy.Request(url=self.browser.current_url, callback=self.parse, 访问链接爬取手机具体品牌和型号的代码: import numpy as np import pandas as pd from selenium import webdriver #1.打开 CSV 文件 file = 'result-taobao.csv' df = pd.read_csv(file,encoding='utf-8') df = df.drop_duplicates(keep='first')# 保存第一条重复数据 df['brand']="" df['type']="" browser = webdriver.Chrome(executable_path=r"C:\Users\xingu\Desktop\chromedriver.exe") for i in range(len(df['link'])): try: #//*[@id="J_Attrs"]/table[1]/tbody/tr[19]/td #//*[@id="J_Attrs"]/table[1]/tbody/tr[6]/td print('----正在爬第',i,'页-----') print(df['link'][i][2:-2]) if 'https:' in df['link'][i][2:-2]: browser.get(df['link'][i][2:-2]) else: browser.get('https:'+df['link'][i][2:-2]) browser.implicitly_wait(5) browser.execute_script('window.scrollTo(0, document.body.scrollHeight)') print('start') df['brand'][i] =
= browser.find_element_by_xpath('//*[@id="J_Attrs"]/table[1]/tbody/tr[19]/td').get_attribute('t extContent') df['type'][i] browser.find_element_by_xpath('//*[@id="J_Attrs"]/table[1]/tbody/tr[20]/td').get_attribute('t extContent') print('1:',df['brand'][i]) except: try: ##tb_attributes > ul.tb-attributes-list.tb-attributes-fix > li:nth-child(1) > p:nth- child(2) df['brand'][i] = browser.find_element_by_css_selector( '#tb_attributes > ul.tb-attributes-list.tb-attributes-fix > li:nth-child(1) > p:nth-child(2)').get_attribute( 'textContent') df['type'][i] = browser.find_element_by_css_selector( '#tb_attributes > ul.tb-attributes-list.tb-attributes-fix > li:nth-child(1) > p:nth-child(3)').get_attribute( 'textContent') print('2:', df['brand'][i]) except: try: df['brand'][i] = browser.find_element_by_css_selector( '#attributes > ul > li:nth-child(3)').get_attribute('textContent') df['type'][i] = browser.find_element_by_css_selector( '#attributes > ul > li:nth-child(4)').get_attribute('textContent') print('3:', df['brand'][i]) except: df['brand'][i]='' df['type'][i]='' print('not find') df.to_csv("result1.csv",encoding="utf-8") 4.淘宝数据的处理: import numpy as np import pandas as pd #1.打开 CSV 文件 file = 'taobao.csv' df = pd.read_csv(file,encoding='utf-8') df = df.drop_duplicates(keep='first')# 只保存第一条重复数据 df.dropna(axis='index', how='all', subset=['brand','type'], inplace=True)#删除品牌和类型为 空的数据 df['brand']=df['brand'].str.replace('品牌: ','')
分享到:
收藏