爬虫
本文最后更新于 2023-10-12,文章内容可能已经过时。
爬虫
立项作品,使用爬虫爬取电商网站的信息,并进行数据分析和展示.
1.京东:
import requests
from bs4 import BeautifulSoup
import xlwt
def get_html(url):
# 模拟浏览器访问
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53'}
print("--> 成功爬取网站信息")
response = requests.get(url, headers=headers) # 请求访问网站
if response.status_code == 200:
html = response.text # 获取网页源码
return html # 返回网页源码
else:
print("获取网站信息失败!")
if __name__ == '__main__':
# 创建workbook,就是创建一个Excel文档
write_work = xlwt.Workbook(encoding='ascii')
# 添加一张单
write_sheet = write_work.add_sheet("sheet1")
# 创建表头
# write_sheet.write(0, 0, label='商品编号') # 第1行 第1列 写入内容'商品编号'
write_sheet.write(0, 0, label='商品名称') # 第1行 第2列 写入内容'商品名称'
write_sheet.write(0, 1, label='价格') # 第1行 第4列 写入内容'价格'
write_sheet.write(0, 2, label='详情页网址') # 第1行 第5列 写入内容'商家'
write_sheet.write(0, 3, label='评价数量') # 第1行 第6列 写入内容'商品详情地址'
# 记录当前行数
_current_row = 0
i=0
k=0
j=0
# 搜索关键字
keyword = input("请输入你要搜索的商品:")
for k in range(0,10):
i = 3+k*2
j = 56+k*60
# 搜索地址
search_url = 'https://search.jd.com/Search?keyword=' + keyword + '&enc=utf-8&page={}&s={}&click=0'.format(i, j)
print(search_url)
html = get_html(search_url)
# 初始化BeautifulSoup库,并设置解析器
soup = BeautifulSoup(html, 'lxml')
# 商品列表
goods_list = soup.find_all('li', class_='gl-item')
# 打印goods_list到控制台
for li in goods_list: # 遍历父节点
# 由于我们第一行已经写入了表头。所以这里0+1,就是从第1行开始,后面每次循环+1
_current_row += 1
if _current_row == 29:
break
# 商品编号
no = li['data-sku']
# 商品名称
name = li.find(class_='p-name p-name-type-2').find('em').get_text()
# 价格
price = li.find(class_='p-price').find('i').get_text()
# 商家
number = 'http:'+li.find(class_='p-commit').find('a')['href']
# 商品详情地址
co = li.find(class_='p-commit').find('a').get_text()
#detail_addr = li.find(class_='p-name p-name-type-2').find('a')['href']
# 写入Excel
#write_sheet.write(_current_row, 0, label=no)
write_sheet.write(_current_row, 0, label=name)
write_sheet.write(_current_row, 1, label=price)
write_sheet.write(_current_row, 2, label=number)
# write_sheet.write(_current_row, 3, label=co)
# 保存文件,使用的是相对目录(也可以使用绝对路径),会保存在当前文件的同目录下。文件名为读取多个商品页面1.xls,必须是.xls后缀
write_work.save("./keyword.xls")
2.天猫:
from selenium import webdriver
import re
driver = webdriver.Chrome()
from selenium import webdriver
import time
import csv
import xlwt
# 搜索商品,获取商品页码
def search_product(key_word):
# 定位输入框
browser.find_element_by_id("q").send_keys(key_word)
# 定义点击按钮,并点击
browser.find_element_by_class_name('btn-search').click()
# 最大化窗口:为了方便我们扫码
browser.maximize_window()
# 等待15秒,给足时间我们扫码
time.sleep(15)
# 定位这个“页码”,获取“共100页这个文本”
page_info = browser.find_element_by_xpath('//div[@class="total"]').text
# findall()返回的是一个列表,虽然此时只有一个元素它也是一个列表。
page = re.findall("(\d+)", page_info)[0]
return page
def main(key_word):
book = xlwt.Workbook(encoding='utf-8', style_compression=0)
sheet = book.add_sheet('爬取商品', cell_overwrite_ok=True)
col = ('商品名称', '商品价格', '付款人数', '店铺名称','发货地')
for i in range(0, 5):
sheet.write(0, i, col[i])
browser.get('https://www.taobao.com/')
page = search_product(key_word)
print(page)
page_num = 1
i=0
while int(page) != page_num:
print("*" * 20)
print("正在爬取第{}页".format(page_num + 1))
browser.get('https://s.taobao.com/search?q={}&s={}'.format(key_word, page_num * 44))
browser.implicitly_wait(15)
# 通过页面分析发现:所有的信息都在items节点下
items = browser.find_elements_by_xpath('//div[@class="items"]/div[@class="item J_MouserOnverReq "]')
for item in items:
# 参数信息
pro_desc = item.find_element_by_xpath('.//div[@class="row row-2 title"]/a').text
# 价格
pro_price = item.find_element_by_xpath('.//strong').text
# 付款人数
buy_num = item.find_element_by_xpath('.//div[@class="deal-cnt"]').text
# 旗舰店
shop = item.find_element_by_xpath('.//div[@class="shop"]/a').text
# 发货地
address = item.find_element_by_xpath('.//div[@class="location"]').text
with open('{}.csv'.format(key_word), mode='a', newline='', encoding='utf-8-sig') as f:
csv_writer = csv.writer(f, delimiter=',')
csv_writer.writerow([pro_desc, pro_price, buy_num, shop, address])
sheet.write(i, 0, pro_desc)
sheet.write(i, 1, pro_price)
sheet.write(i, 2, buy_num)
sheet.write(i, 3, shop)
sheet.write(i, 4, address)
i+=1
page_num += 1
path = 'D:/' + key_word + '.xls'
book.save(path)
print("数据爬取完毕!")
if __name__ == '__main__':
key_word = input("请输入你要搜索的商品:")
browser = webdriver.Chrome()
main(key_word)
3.淘宝:
import re
import time
from concurrent.futures import ThreadPoolExecutor
import matplotlib.pyplot as plt
import pymysql
import requests
import seaborn as sns
import xlwt
from selenium import webdriver
import random
# 爬取网页部分
# 使用selenium自动获取cookie
# 因为解决不了淘宝滑块等验证的问题,此方法暂不可行
def getCookie():
options = webdriver.Chrome
dr = webdriver.Chrome(r'C:\Users\wpy\AppData\Local\Google\Chrome\Application\chromedriver_win32')
dr.get('https://s.taobao.com/search?q=狗')
cookie_test = dr.get_cookies()
# 未整理的cookie
print(cookie_test)
cookie = [item["name"] + "=" + item["value"] for item in cookie_test]
cookiestr = '; '.join(item for item in cookie)
# 整理后的cookie
print(cookiestr)
# 获取网页的html文档
# 具体思路是手动获取cookie,把cookie存入文件夹中,从文件夹中读取cookie进行爬取
def getHTML(name, page):
try:
# 爬取数据过多会导致淘宝安全系统认为我们是爬虫从而停止且ip被封,所以尝试使用代理池解决,首先使用付费代理,获取含有ip地址的api,然后把获取到的ip地址手动的存入程序中
# proxy = ['106.32.9.201:4231', '58.63.37.245:4245', '27.156.212.245:4213', '218.91.4.107:4212',
# '117.57.20.217:4226', '222.190.198.122:4231', '123.158.127.209:4281']
# # 准备好的代理ip
# proxy1 = proxy[1]
# new_data = {
# "http": "123.158.127.209:4281"
# }
start_url = 'https://s.taobao.com/search?q=' + name
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/70.0'
}
path = 'D:\mycookie.txt'
with open(path, 'r') as f:
mycookies = f.read()
mycookies = mycookies.split(';')
cookies = {}
for cookie in mycookies:
name, value = cookie.strip().split('=', 1)
cookies[name] = value
goods = ''
for i in range(0, 1):
i = int(page)
if i == 0:
url = start_url
else:
url = start_url + '&s=' + str(44 * i)
# r = requests.get(url, headers=header, cookies=cookies, timeout=60,proxies=new_data)
r = requests.get(url, headers=header, cookies=cookies, timeout=60)
r.encoding = r.apparent_encoding
goods += r.text
print('获取网页文档成功!')
return goods
except:
print('获取网页文档失败!' + '已爬取到第' + str(i) + '页')
# 解析网页部分
# 使用正则表达式匹配得到想要的字段,存储在列表中
def findMS(html):
try:
marketnames = re.findall('"nick":"(.*?)"', html)
titles = re.findall('"raw_title":"(.*?)"', html)
prices = re.findall('"view_price":"(.*?)"', html)
pays = re.findall('"view_sales":"(.*?)"', html)
data = []
for i in range(len(titles)):
data.append([marketnames[i], titles[i], prices[i], pays[i]])
print('解析网页成功!')
return data
except:
print('解析网页失败!')
# 数据处理部分
# 按照价格进行用户定制的升降序排序
# 升序
def sort1(data):
for i in range(len(data) - 1):
for j in range(len(data) - i - 1):
if float((data[j])[2]) > float((data[j + 1])[2]):
data[j], data[j + 1] = data[j + 1], data[j]
return data
# 降序
def sort2(data):
for i in range(len(data) - 1):
for j in range(len(data) - i - 1):
if float((data[j])[2]) < float((data[j + 1])[2]):
data[j], data[j + 1] = data[j + 1], data[j]
return data
# 数据持久化部分
# 存入Excel:
def download(data, name, page):
try:
if len(data) != page * 44:
print("当前data元素个数为:" + str(len(data)))
print("预期data元素个数为:" + str(page * 44))
number = len(data)
else:
number = page * 44
book = xlwt.Workbook(encoding='utf-8', style_compression=0)
sheet = book.add_sheet('爬取商品', cell_overwrite_ok=True)
col = ('商铺名称', '商品', '价格', '购买人数')
for i in range(0, 4):
sheet.write(0, i, col[i])
for k in range(0, number):
datalist = data[k]
for j in range(0, 4):
sheet.write(k + 1, j, datalist[j])
path = 'D:/' + name + '.xls'
book.save(path)
print('存入Excel成功!')
except:
print('存入Excel失败!')
# 存入mysql数据库:
def sql(name, data):
try:
# 获取连接对象conn,建立数据库的连接
conn = pymysql.connect(host='localhost', port=3306, user='root', passwd='123456', db='dbcourses',
charset='utf8')
# db:表示数据库名称
# 进行连接数据库服务端(host 访问服务端的ip,user 访问服务端的用户,password访问服务端的用户密码,database 访问服务端的数据库,charset 访问时采用的编码方式)
cur = conn.cursor()
sql1 = 'create table ' + str(
name) + '(id int not null,shop varchar(225),commodity varchar(225),price varchar(225),number varchar(225));'
sql1 = str(sql1)
cur.execute(sql1)
# 二次拼接得到sql语句
for i in range(0, len(data)):
sql11 = 'insert into '
sql22 = '(id,shop,commodity,price,number) values('
sql33 = str(i)
sql44 = ','
sql55 = '"'
sql77 = ');'
sql66 = sql11 + name + sql22 + sql33 + sql44 + sql55 + str(data[i][0]) + sql55 + sql44 + sql55 + str(
data[i][1]) + sql55 + sql44 + sql55 + str(data[i][2]) + sql55 + sql44 + sql55 + str(
data[i][3]) + sql55 + sql77
sql4 = str(sql66)
cur.execute(sql4)
conn.commit()
cur.close()
conn.close()
print('存入数据库成功!')
except:
print('存入数据库失败!')
# 数据可视化部分
# 使用直方图表现价格趋势
def view(data):
name = []
price = []
for i in range(len(data) - 1):
name.append(i)
price.append(data[i][2])
# 用Matplotlib画条形图
plt.bar(name, price)
plt.show()
# 用Seaborn画条形图
sns.barplot(name, price)
plt.show()
def main():
# 用户输入
name = input('请输入爬取商品的名字:')
page = input('请输入你想要爬取的页数:')
sort = input('请输入你想要的价格排序方式:升序请输入1,降序请输入2:')
sort = int(sort)
page = int(page)
# 爬取数据
data1 = []
for i in range(0, int(page)):
html = getHTML(name, page)
data = findMS(html)
# 猜测爬取数据过多被封,可能是爬取频率的问题,故此处随机设置间隔尝试解决此问题
time.sleep(random.randint(1, 10))
# print("当前数据长度为:" + str(len(data)))
if len(data) == 0:
print("数据有误!当前页数为" + str(i))
print(data)
print(html)
data1 += data
data = []
# # 数据处理
# if sort == 1:
# data = sort1(data)
# if sort == 2:
# data = sort2(data)
# 数据持久化
download(data1, name, page)
# sql(name, data)
# 数据可视化
# view(data)
# 创建线程池:提高爬取的效率
if __name__ == "__main__":
pool = ThreadPoolExecutor(max_workers=2)
future1 = pool.submit(main())
pool.shutdown()
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果