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('品牌: ','')