目录
day05
1.json模块
- json.loads()
json格式(对象,数组) ->Python(字典,列表) - json.dumps()
Python(字典,元组,列表) -> json(对象,数组)
2.Ajax动态加载
- 抓包工具抓参数:WebForms -> QueryString
- params = {QueryString中的一堆查询参数}
- URL地址写:抓包工具Raw下的GET地址
.3.selenium + phantomjs
- sekenium:Web自动化测试工具
- phantomjs:无界面浏览器(在内存执行页面加载)
- 使用步骤
- 导入模块
from selenium import webdriver
from selenium.webdriver.common.keys import Keys - 创建浏览器对象
driver = webdriver.PhantomJS(executable_path="...") - 获取网页信息
driver.get(url) - 查找节点位置
ele = driver.find_element_by_id("") - 发送文字
ele.send_keys("") - 点击
cli = driver.find_element_by_class_name("")
cli.click() - 关闭
driver.quit()
- 导入模块
- 常用方法
- driver.get(url)
- driver.page_source
- driver.page_source.find('字符串')
失败:-1
成功:非-1 - driver.find_element_by_name("属性值")
- driver.find_elements_by_xpath("xpath表达式")
- 对象名.send_keys("")
- 对象名.click()
- 对象名.text
- driver.quit()
4.selenium + chromedriver
- chromedriver
Chrome的 Webdriver - 安装
- 下载对应版本的chromedriver安装包
https://chromedriver.storage.googleapis.com/index.html - 将 chromedriver.exe 放到python安装目录的Scripts目录
- 下载对应版本的chromedriver安装包
- 如何设置无界面模式
opt = webdriver.ChromeOptions()
opt.set_headless()
driver = webdriver.Chrome(options=opt)
driver.get(...) - driver如何执行JavaScript
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
day06
1.多线程爬虫
- 进程线程回顾
- 进程
- 系统中正在运行的一个应用程序
- 1个CPU核心1次只能执行1个进程,其他进程处于非运行状态
- N个CPU核心可以同时执行N个任务
- 线程
- 进程中包含的执行单元,1个进程可包含多个线程
- 线程可使用所属进程的空间(1次只能执行1个线程,阻塞)
- 锁:防止多个线程同时使用共享空间
- GIL:全局解释锁
执行通行证,仅此一个,拿到了通行证可执行,否则 等 - 应用场景
- 多进程:大量的密集的计算
- 多线程:I/O密集
爬虫:网络I/O多,适合多线程
写文件:本地磁盘I/O
- 进程
- 案例:使用多线程爬取 百思不得其解 段子
- 爬取目标:段子内容
- URL:http://www.budejie.com/
- xpath表达式://div[@class="j-r-list-c-desc"]/a/text()
- 知识点
- 队列(from queue import Queue)
put()
get()
Queue.empty():是否为空
Queue.join():如果队列为空,执行其他程序 - 线程(import threading)
threading.Thread(target=...)
- 队列(from queue import Queue)
- 代码实现
'''01_多线程爬取百思不得其姐案例.py''' import requests from lxml import etree from queue import Queue import threading import time class bsSpider: def __init__(self): self.baseurl = "http://www.budejie.com/" self.headers = {"User-Agent":"Mozilla/5.0"} # url队列 self.urlQueue = Queue() # 响应队列 self.resQueue = Queue() # 生成URL队列 def getUrl(self): for pNum in range(1,51): # 拼接URL url = self.baseurl + str(pNum) self.urlQueue.put(url) # 响应队列 def getHtml(self): while True: url = self.urlQueue.get() res = requests.get(url,headers=self.headers) res.encoding = "utf-8" html = res.text # 放到响应队列 self.resQueue.put(html) # 清除此任务 self.urlQueue.task_done() # 解析页面 def getContent(self): while True: # 从响应队列中依次获取html源码 html = self.resQueue.get() parseHtml = etree.HTML(html) r_list = parseHtml.xpath('//div[@class="j-r-list-c-desc"]/a/text()') for r in r_list: print(r+"\n") # 清除任务 self.resQueue.task_done() def run(self): # 存放所有的线程 thread_list = [] # 获取url队列 self.getUrl() # 创建getHtml线程 for i in range(5): threadRes = threading.Thread(target=self.getHtml) thread_list.append(threadRes) # 解析线程 for i in range(3): threadParse = threading.Thread(target=self.getContent) thread_list.append(threadParse) # 所有线程开始干活 for th in thread_list: th.setDaemon(True) th.start() # 如果队列为空,则执行其他程序 self.urlQueue.join() self.resQueue.join() print("运行结束") if __name__ == "__main__": begin = time.time() spider = bsSpider() spider.run() end = time.time() print(end-begin)
2.BeautifulSoup
- 定义
HTML或XML的解析器,依赖于1xml - 安装
python -m pip install beautifulsoup4
导模块:
from bs4 import BeautifulSoup - 使用流程
- 导入模块
from bs4 import BeautifulSoup - 创建解析对象
soup = Beautifulsoup(html,'1xml') - 查找节点对象
soup.find_all(class="属性值")
- 导入模块
- 示例代码
'''02_BeautifulSoup示例.py''' from bs4 import BeautifulSoup html = '<div class="test">雄霸</div>' # 创建解析对象 soup = BeautifulSoup(html,'lxml') # 查找节点 #r_list = soup.find_all(class_="test") r_list = soup.find_all("div",attrs={"class":"test"}) for r in r_list: print(r.get_text())
'''03_BeautifulSoup示例2.py''' from bs4 import BeautifulSoup html = '''<div class="test">雄霸</div> <div class="test">幽若</div> <div class="test2"> <span>第二梦</span> </div> ''' soup = BeautifulSoup(html,'lxml') # class为test的div的文本内容 #divs = soup.find_all("div",attrs={"class":"test"}) for div in divs: print(div.string) print(div.get_text()) # class为test2的div下的span中文本内容 divs = soup.find_all("div",attrs={"class":"test2"}) for div in divs: print(div.span.string)
- BeautifulSoup支持的解析库
- lxml:BeautifulSoup(html,'1xml')
速度快,文档容错力强 - python标准库:BeautifulSoup(html,'html.parser')
速度一般 - xml解析器:BeautifulSoup(html,'xml')
速度快,文档容错力强
- lxml:BeautifulSoup(html,'1xml')
- 节点选择器
- 选择节点
soup.节点名:soup.a 、soup.ul - 获取文本内容
soup.节点名.string
- 选择节点
- 常用方法
- find_all():返回列表
- r_list = soup.find_all(属性名="属性值")
r_list = soup.find_all(class_="test") - r_list = soup.find_all('节点名',attrs={'名':'值'})
r_list = soup.find_all('div',attrs={"class":"test"})
- r_list = soup.find_all(属性名="属性值")
- 示例:
'''04_糗事百科BeautifulSoup.py''' import requests from bs4 import BeautifulSoup url = "https://www.qiushibaike.com/" headers = {"User-Agent":"Mozilla/5.0"} res = requests.get(url,headers=headers) res.encoding = "utf-8" html = res.text # 创建解析对象 soup = BeautifulSoup(html,'lxml') r_list = soup.find_all("div",attrs={"class":"content"}) for r in r_list: s = r.span.get_text().strip() print(s) print("*" * 30)
- find_all():返回列表
3.Scrapy框架
- 安装
- 安装(Ubuntu)
- 安装依赖库
sudo apt-get install python3-dev build-essential libssl-dev libffi-dev libxml2 libxml2-dev libxslt1-dev zlib1g-dev - 升级pyasn1模块
sudo pip3 install pyasn1==0.4.4 - 安装Scrapy
sudo pip3 install Scrapy
- 安装依赖库
- 安装(Ubuntu)
4.Scrapy框架
- Scrapy框架
异步处理框架,可配置和可扩展程度非常高,Python中使用最广泛的爬虫框架 - 框架组成
- 引擎(Engine):整个框架核心
- 调度器(Scheduler):接受从引擎发过来的URL,入队列
- 下载器(Downloads):下载网页源码,最终返回给爬虫程序
- 项目管道(Item Pipeline):数据处理
- 下载器中间件(Downloader Middlewares):
处理引擎与下载器之间的请求与响应 - 蜘蛛中间件(Spider Middlerwares):
处理爬虫程序输入响应和输出结果以及新的请求 - Item:定义爬取结果的数据结构,爬取的数据会被赋值为Item对象
- Scrapy框架的爬取流程
- 制作Scrapy爬虫项目步骤
- 新建项目
scrapy startproject 项目名 - 明确目标(items.py)
- 制作爬虫程序
xxx/spiders:scrapy genspider 文件名 域名 - 处理数据(pipelines.py)
- 配置settings.py
- 运行爬虫项目
scrapy crawl 爬虫名
- 新建项目
- scrapy项目文件详解
- 目录结构
testspider/ ├── scrapy.cfg #项目基本配置文件,不用改 └── testspider ├── __init__.py ├── items.py # 定义爬取数据的结构 ├── middlewares.py # 下载器中间件和蜘蛛中间件实现 ├── pipelines.py # 处理数据 ├── settings.py # 项目全局配置 └── spiders # 存放爬虫程序 ├── __init__.py ├── myspider.py
- settings.py配置
# 是否遵守robots协议,该为False ROBOTSTXT_OBEY = False # 最大并发量,默认为16个 CONCURRENT_REQUESTS = 32 # 下载延迟时间为3秒 DOWNLOAD_DELAY = 3 # 请求报头 DEFAULT_REQUEST_HEADERS = { 'User-Agent': "Mozilla/5.0", 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en', } # 蜘蛛中间件 SPIDER_MIDDLEWARES = { 'testspider.middlewares.TestspiderSpiderMiddleware': 543, } # 下载器中间件 DOWNLOADER_MIDDLEWARES = { 'testspider.middlewares.TestspiderDownloaderMiddleware': 543, } # 管道文件 ITEM_PIPELINES = { 'testspider.pipelines.TestspiderPipeline': 300, }
- 示例:抓取百度首页源码,存到baidu.html中
- scrapy startproject baidu
- cd baidu/baidu
- subl items.py(此示例可不用操作)
- cd spiders
- scrapy genspider baiduspider baidu.com
#爬虫名
#域名
#start_urls
def parse(self,response):
with open('baidu.html','w') as f:
f.write(response.text) - subl settings.py
- 关闭robots协议
- 添加Headers
- cd spiders
- scrapy crawl baiduspider
- 目录结构
5.pycharm运行scrapy项目
- 创建文件begin.py
和scrapy.cfg同目录
from scrapy import cmdline
cmdline.execute("scrapy crawl baiduspider".split()) - 在
Run -> Editconfigurations -> + -> python
name : spider
Script : begin.py的路径
working directory : 你自己的项目路径 - 打开begin.py
右上角 - 点运行
今日示例