wkyuu
c372046c7b
|
3 years ago | |
---|---|---|
README.md | 3 years ago | |
downloader.py | 3 years ago | |
historyPrice.py | 3 years ago | |
middlewares.py | 3 years ago | |
milkSpider.py | 3 years ago | |
pipelines.py | 3 years ago | |
settings.py | 3 years ago |
README.md
milkSpider
selenium + redis + 分布式 + xpath + etree + 可视化
任务:爬取京东网站上在售的各类牛奶品类的商品名称,简介,价格相关,评论区相关。并给出相应的价格波动趋势,精选好评,用python的可视化展示。计划任务自动爬取。
TODO
-
初始化 selenium 框架,编写好相应的爬取规则,初步实现小规模爬取内容
-
从历史价格网页爬取历史价格
- 同时/后期追加 存入csv 价格趋势,涨跌幅。比对,给出价格波动趋势
-
加入Redis分布式设计
-
数据可视化
- 使用python终端绘图,需要解决如何选取想要展示的条例
-
python打包exe,需要图形化界面?
project
项目目录
Selesium
downloader.py 下载器,即爬取内容
middlewares.py 配置分布式,线程,redis相关内容
pipelines.py 处理得到的数据,存储到相应文件
milkSpider.py 主文件,配置爬取设置,自动化等
historyPrice.py 爬取历史价格
selenium
配置下载器,利用selenium模拟浏览器正常浏览行为
# -*- coding: utf-8 -*-
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from lxml import etree
def getsource(url):
init = Options()
init.add_argument('--no-sandbox')
init.add_argument('--headless')
init.add_argument('--disable-gpu')
init.add_argument("disable-cache")
init.add_argument('disable-infobars')
init.add_argument('log-level=3') # INFO = 0 WARNING = 1 LOG_ERROR = 2 LOG_FATAL = 3 default is 0
init.add_experimental_option("excludeSwitches",['enable-automation','enable-logging'])
driver = webdriver.Chrome(chrome_options = init)
driver.implicitly_wait(10)
driver.get(url)
response = etree.HTML(driver.page_source)
response = etree.tostring(response, encoding = "utf-8", pretty_print = True, method = "html")
response = response.decode('utf-8')
driver.close()
return response
安装,初始化
GIT
# 安装git
winget install --id Git.Git -e --source winget
## 或者官网下载
https://git-scm.com/download/win
# 在powershell中使用
vim $PROFILE
## 修改相应的位置为 GITPATH = ~/Git/cmd/git.exe
## SetAlias git $GITPATH
git init
git remote add origin https://bdgit.educoder.net/mf942lkca/milkSpider.git
git pull https://bdgit.educoder.net/mf942lkca/milkSpider.git
git remote -v # 查看远程仓库信息
touch .gitignore # 创建忽略上传控制文件
git add *.py # 添加要push的本地内容到一个本地临时仓库
git commit -m "update" # 先添加一个commit
git push -u origin master # push, 出错就 -f(注意会造成不可回避的损失)
selenium
安装
# 安装selenium
pip3 install selenium
# 查看配置信息
pip how selenium
调用时导入的内容
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
# chrome_options.add_argument('lang=zh_CN.UTF-8') # 设置中文
chrome_options.add_argument('--headless') # 无界面
chrome_options.add_argument('--no-sandbox') # 解决DevToolsActivePort文件不存在报错问题
chrome_options.add_argument('--disable-gpu') # 禁用GPU硬件加速。如果软件渲染器没有就位,则GPU进程将不会启动。
chrome_options.add_argument('--disable-dev-shm-usage')
chrome_options.add_argument('--window-size=1920,1080') # 设置当前窗口的宽度和高度
driver = webdriver.Chrome('chromedriver',chrome_options=chrome_options)
#driver = webdriver.Chrome()
url = ""
driver.get(url)
print(driver.page_source)
driver.quit()
一些备忘录
text = """this is test content;这是测试内容。"""
html1 = etree.HTML(text)
# html1 = etree.fromstring(text) # 同HTML()
# 方法1 使用html.unescape()
res = etree.tostring(html1)
print(html.unescape(res.decode('utf-8')))
# 方法2 使用uft-8编码
res = etree.tostring(html1,encoding="utf-8") # 这种方法对标签用的中文属性无效
print(res.decode('utf-8'))
# 方法1 使用open读取文档做字符串处理
with open('test.html') as f:
html1 = etree.HTML(f.read())
# 之后代码同 处理字符串 的两种方法
# 方法2 parse读取文档时指定编码方式
html1 = etree.parse('test.html',etree.HTMLParser(encoding='utf-8'))
# 这里要指定正确(与所读取文档相应的编码)的编码方式,不然后面会出现乱码
# 之后代码同 处理字符串 的两种方法
请求头,cookie等
# 访问 https://httpbin.org/get?show_env=1 可以返回当前浏览器的请求信息
options.add_argument('lang=zh_CN.UTF-8')
# 贴一个用json模块保存cookies
def getCookies():
with open('cookies.json', 'r', encoding='utf-8') as fd:
listCookies = json.loads(fd.read())
for cookie in listCookies:
cookies = {
'domain': cookie['domain'],
'httpOnly': cookie['httpOnly'],
'name':cookie['name'],
'path':'/',
'secure': cookie['secure'],
'value':cookie['value'],
}
print(cookies)
def saveCookies(driver):
jsonCookies = json.dumps(driver.get_cookies())
with open('cookies.json', 'w', encoding='utf-8') as fd:
fd.write(jsonCookies)
ChromeDriver
下载 ChromeDriver 放到当前目录就行(如果是放在 python 根目录可以不用在实例化 selenium 时指定chromedriver 路径)
Requests
经典老碟
import requests
Redis
# 安装 redis 模块
## pip install redis
# 实例对象
redisconn = redis.Redis(host = '127.0.0.1', port = '6379', password = 'x', db = 0)
# redis 取出的结果默认是字节,我们可以设定 decode_responses=True 改成字符串
备注
在没有使用线程之前,完整跑完五个种类共(30 x 10 x 5 = 1500)条数据,用时365s
使用线程数为5的情况下,完整跑完五个种类共 1500条数据,用时130s
使用线程数为16的情况下,完整跑完五个种类共 1500条数据,用时80s
1,在爬取的视频评论很多的情况下,效率太低,且频次太高了容易被ban。应该设定一下,比如说只爬几页,或者只爬热门评论。而且。。哔哩哔哩的评论区是其他加载的,本爬虫在requests.get的时候,会多次爬取,太危险了。为了一条数据就多次访问,被ban风险更高了。可以改成,对单个页面就取一次网页源代码,但是这个需要真实浏览器来访问才能拿到(selenium框架),然后对这个源代码进行数据提取操作,这样可以比较好地减少爬虫访问量,降低被ban的风险。
2,爬虫结构是先完全爬取数据,存到临时内存中,最后才存入文件。风险太大,如果中途被ban了,容易导致整个爬取的过程前功尽弃,且之前数据全都丢失。
2.1,线程作用效果应为
结构:视频{页数{父评论{子评论}}}
采用多线程爬取父评论+子评论,也就是一次能对多个父子评论爬取数据;或者采用多线程爬取页数中的评论,一次能爬取多个页面。后者效率更高。
2.2,但是由于该爬虫设计结构是把全部数据都先爬取再存起来,这样子要求线程对同一个字符串结构进行数据追加,容易导致混乱(即 在线程优先级不同的情况下,多个线程同时操作一个全局字符串,可能上一条还是父评论,下一条就变成另一条父评论的子评论了。)。
2.3,整改建议是:采用多线程对多个页面爬取数据,某个线程结束时即爬完一页就把该页对应的字符串存到csv文件中,采用线程锁来控制每次存数据时都仅单个占用csv文件,防止数据混乱。这一步需要修改数据的存储过程的流程。
3,爬取效果不好,爬取父评论+子评论的方式,实际上意义不大。意思就是父和子评论都混到一起了,没有主次效果,应该加个标示便于直观显示。
参考链接
1,selenium+python自动化100-centos上搭建selenium启动chrome浏览器headless无界面模式
2,解决:'chromedriver' executable needs to be in PATH问题
3,Python selenium-chrome禁用打印日志输出
13,python selenium 保存cookie 读取cookie
17,