目录
2、无头浏览器or需要js加载的界面(暂时只放selenium了之后可能会更新Pyppeteer)
1、requests 模块
-
response的属性以及类型
response.text : 获取网站源码 response.encoding :访问或定制编码方式 response.url :获取请求的url response.content :响应的字节类型 response.status_code :响应的状态码 response.headers :响应的头信息 类型 :models.Response
-
get请求
import requests #请求地址 url = 'http://www.baidu.com/s?' #请求头 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0' } #请求参数(path参数是可以的) data = { 'wd':'北京' } print(requests.get(url,params=data,headers=headers))
-
post请求
import requests post_url = 'https://fanyi.baidu.com/sug' headers={ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0' } data = { 'kw': 'eye' } r = requests.post(url = post_url,headers=headers,data=data) print(r.text) #get请求的参数名字是params post请求的参数的名字是data
-
代理
#在请求中设置proxies参数 #参数类型是一个字典类型 其实就是get的多一个参数 import requests url = 'http://www.baidu.com/s?' headers = { 'user‐agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36' } data = { 'wd':'ip' } proxy = { 'http':'219.149.59.250:9797' } r = requests.get(url=url,params=data,headers=headers,proxies=proxy) with open('proxy.html','w',encoding='utf‐8') as fp: fp.write(r.text)
-
验证码
#要根据特殊的特殊对待 #先给一个例子,一点一点剖析 # 通过登陆 然后进入到主页面 # 通过找登陆接口我们发现 登陆的时候需要的参数很多 # _VIEWSTATE: /m1O5dxmOo7f1qlmvtnyNyhhaUrWNVTs3TMKIsm1lvpIgs0WWWUCQHl5iMrvLlwnsqLUN6Wh1aNpitc4WnOt0So3k6UYdFyqCPI6jWSvC8yBA1Q39I7uuR4NjGo= # __VIEWSTATEGENERATOR: C93BE1AE # from: http://so.gushiwen.cn/user/collect.aspx # email: 595165358@qq.com # pwd: action # code: PId7 # denglu: 登录 # 我们观察到_VIEWSTATE __VIEWSTATEGENERATOR code是一个可以变化的量 # 难点:(1)_VIEWSTATE __VIEWSTATEGENERATOR 一般情况看不到的数据 都是在页面的源码中 # 我们观察到这两个数据在页面的源码中 所以我们需要获取页面的源码 然后进行解析就可以获取了 # (2)验证码 import requests # 这是登陆页面的url地址 url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36' } # 获取页面的源码 response = requests.get(url = url,headers = headers) content = response.text # 解析页面源码 然后获取_VIEWSTATE __VIEWSTATEGENERATOR from bs4 import BeautifulSoup soup = BeautifulSoup(content,'lxml') # 获取_VIEWSTATE viewstate = soup.select('#__VIEWSTATE')[0].attrs.get('value') # 获取__VIEWSTATEGENERATOR viewstategenerator = soup.select('#__VIEWSTATEGENERATOR')[0].attrs.get('value') # 获取验证码图片 code = soup.select('#imgCode')[0].attrs.get('src') code_url = 'https://so.gushiwen.cn' + code # 有坑 # import urllib.request # urllib.request.urlretrieve(url=code_url,filename='code.jpg') # requests里面有一个方法 session() 通过session的返回值 就能使用请求变成一个对象 session = requests.session() # 验证码的url的内容 response_code = session.get(code_url) # 注意此时要使用二进制数据 因为我们要使用的是图片的下载 content_code = response_code.content # wb的模式就是将二进制数据写入到文件 with open('code.jpg','wb')as fp: fp.write(content_code) # 获取了验证码的图片之后 下载到本地 然后观察验证码 观察之后 然后在控制台输入这个验证码 就可以将这个值给 # code的参数 就可以登陆 code_name = input('请输入你的验证码') # 点击登陆 url_post = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx' data_post = { '__VIEWSTATE': viewstate, '__VIEWSTATEGENERATOR': viewstategenerator, 'from': 'http://so.gushiwen.cn/user/collect.aspx', 'email': '595165358@qq.com', 'pwd': 'action', 'code': code_name, 'denglu': '登录', } response_post = session.post(url = url, headers = headers, data = data_post) content_post = response_post.text with open('gushiwen.html','w',encoding= ' utf-8')as fp: fp.write(content_post) # 难点 # (1) 隐藏域 # (2) 验证码 #验证码基本都用第三方,第三方的也蛮便宜
2、无头浏览器or需要js加载的界面(暂时只放selenium了之后可能会更新Pyppeteer)
-
chromedriver
因为chrome会一直更新,所以这里会放一下如何下载chromedriver
-
只要在网上随便找一个你chorme对应的chromedriver版本比如说119.xxxx.xxx,如何替换下载地址的版本号就行
-
chromedriver下载地址(win版):https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/120.0.6099.62/win32/chromedriver-win32.zip
-
最新版本的chromedriver:Chrome for Testing availability
-
不想陪环境变量,直接解压之后把exe拖到工程项目中就行
-
-
selenium使用
#1.导入 from selenium import webdriver #2.创建浏览器操作对象 browser = webdriver.Chrome() #3.访问网站 url = 'https://www.baidu.com/' #browser.get(url) #4.page_source获取网页源码 content = browser.page_source print(content)
-
selenium语法
1.find element by id eg:button = browser.find element by_id('su') 2.find elements by name eg:name = browser.find element by name('wd') 3.find elements by_xpath eg:xpath1 = browser.find elements by_xpath('//input[@id="su"]') 4.find elements by_tag name eg:names = browser.find elements by_tag name('input') 5.find elements by_css selector eg:my_input = browser.find elements by_css selector('#kw')[o] 6.find elements by link text eg:browser.find element by link text("新闻") 7.获取元素属性 get_attribute('class') 8.获取元素文本 .text 9.获取标签名 tag name 10.交互 点击:click() 输入:send keys() 后退操作:browser.back() 前进操作:browser.forword() 模拟JS滚动: js='document.documentElement.scrollTop=10000browser.execute script(js) 执行js代码 获取网页代码: page_source 退出: browser.quit()
-
headless(无头浏览器)
from selenium import webdriver from selenium.webdriver.chrome.options import Options def share_brower(): chrome_options = Options() chrome_options.add_argument('--headless') chrome_options.add_argument('--disable-gpu') # path是你自己的chrome浏览器的文件路径 path = r'C:\Program Files\Google\Chrome\Application\chrome.exe' chrome_options.binary_location = path browser = webdriver.Chrome(options=chrome_options) return browser browser = share_brower() url = 'https://www.baidu.com' browser.get(url)
二、数据解析
1、xpath使用方法及基本语法
-
使用方法
1、导包 from lxml import etree 2、etree.parse()解析本地文件 html tree = etree.parse( 'xx.html') 3、etree.HTML()服务器响应文件 html_tree = etree.HTML(response.read().decode('utf-8').html 4、tree.xpath(xpath路径)
-
基本语法
xpath基本语法 1.路径查询 //: 查找所有子孙节点,不考虑层级关系 / : 找直接子节点 2.谓词查询 //div[@id] //div[@id="maincontent"] 3.属性查询 //@class 4.模糊查询 //div[contains(@id,"he")] //div[starts-with(@id,"he")] 5.内容查询 //div/h1/text() 6.逻辑运算 //div[@id="head" and @class="s down"] //title | //price
2、JSONPath使用和学习
-
使用
1、导包 pip install jsonpath 2、jsonpath的使用: obj = json.load(open('<json文件>','r',encoding='utf-8")) ret = jsonpath.jsonpath(obj,'<jsonpath语法>')
-
基本语法
秉承站在巨人的肩膀上,我们直接学习这位巨人的讲解:JSONPath-简单入门-CSDN博客
3、BeautifulSoup
-
使用
1.导入 from bs4 import BeautifulSoup 2.创建对象 服务器响应的文件生成对象 soup = Beautifulsoup(response.read().decode(),lxml') 本地文件生成对象 soup = Beautifulsoup(open(1.html'),'lxml') 注意:默认打开文件的编码格式gbk所以需要指定打开编码格式
-
基本语法
3.节点定位 (1)根据标签名查找节点 soup.a[注]只能找到第一个a soup.a.name soup.a.attrs (2)函数 <1>.find(返回一个对象) find('a'): 只找到第一个a标签 find('a',title=名字) find('a',class_=名字') 注意有下划线哦 <2>.find all(返回一个列表) find all(a) 查找到所有的a find all(['a’,'span']) 返回所有的a和span find all('a',limit=2) 只找前两个a (3)select(根据选择器得到节点对象)[推荐] <1>element eg:p <2>.class eg:.firstname <3>#id eg:#firstname <4>属性选择器 [attribute] eg:li = soup.select('li[class]') [attribute=value] eg:li = soup.select('li[class="hengheng1"]') <5>层级选择器 element element div p element>element div>p element,element div,p eg:soup = soup.select('a,span') 4.节点信息 (1)获取节点内容: 适用于标签中嵌套标签的结构 obj.string obj.get_text()[推荐] (2)节点的属性 tag.name 获取标签名 eg:tag = find(li) print(tag.nametag.attrs将属性值作为一个字典返回 (3)获取节点属性 obj.attrs.get('title')[常用] obj.get('title') obj['title']
三、数据导出
因为本文的主要内容是爬虫实现已经方便之后使用爬虫时快速阅读,数据存储我就不赘述了,如果想学习的伙伴可以根据下面框架自行学习。(参考自Python 学习路线 by 程序员鱼皮 | 鱼皮的编程宝典 (codefather.cn))
-
文件
-
Excel
-
CSV
-
-
数据库
-
MongoDB
-
MySQL
-
-
中间件
-
Redis
-
四、简单爬虫
import requests
from bs4 import BeautifulSoup
headers = {
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0"
}
for startNum in range(0,250,25):
response = requests.get(f"https://movie.douban.com/top250?start={startNum }", headers=headers)
# print(response.status_code)
if response.ok:
content = response.text
soup = BeautifulSoup(content, "html.parser")
allTitles = soup.find_all("span", attrs={"class": "title"})
for title in allTitles:
if "/" not in title.string:
print(title.string)
五、scrapy框架学习
1、项目创建
-
spider项目生成
scrapy startproject <项目名称>
eg:
scrapy startproject myspiderproject1
-
项目框架介绍
│- scrapy.cfg ->项目的配置文件 │ └─myspiderproject1 │ items.py ->自己预计需要爬取的内容 │ middlewares.py ->自定义中间件的文件(代理) │ pipelines.py ->管道,清洗并保存数据 │ settings.py ->设置文件,UA,启动管道 │ __init__.py │ └─spiders ->自己定义的spider的文件夹 __init__.py
2、简单创建爬虫及执行
-
创建爬虫
先进入创建的文件夹下(注意只进入第一层文件夹)
cd <项目名称>
再创建爬虫实体:
scrapy genspider <爬虫实体名> <要爬虫的域名>
eg:
cd myspiderproject1 scrapy genspider itcast itcast.cn
文件夹结构
│ scrapy.cfg │ └─myspiderproject1 │ items.py │ middlewares.py │ pipelines.py │ settings.py │ __init__.py │ ├─spiders │ │ itcast.py ->爬虫实体 │ │ __init__.py │ │ │ └─__pycache__ │ itcast.cpython-39.pyc │ __init__.cpython-39.pyc │ └─__pycache__ settings.cpython-39.pyc __init__.cpython-39.pyc
-
爬虫实体文件及其内容
import scrapy class ItcastSpider(scrapy.Spider): name = 'itcast' allowed_domains = ['itcast.cn'] start_urls = ['http://itcast.cn/'] #初始爬虫网页 def parse(self, response): #定义针对文件 with open("itcast.html","wb") as f: f.write(response.body)
-
执行爬虫
注意是在终端里
scrapy crawl <爬虫实体名字>
eg:
scrapy crawl itcast
response常见方法: response.text ‐‐‐》响应的是字符串 response.body ‐‐‐》响应的是二进制文件 response.xpath() --‐》xpath方法的返回值类型是selector列表 response.xpath().extract() ‐‐‐》提取的是selector对象的是data response.xpath().extract_first() ‐‐‐》提取的是selector列表中的第一个数据
3、完整使用scrapy框架进行爬虫过程
-
创建项目
scrapy startproject <项目名称>
这里反正框架有点奇怪,他创建完是两层文件夹形式,我们要进入第一层文件夹下再创建下一步的爬虫文件:
cd <项目名称>
-
创建爬虫文件
scrapy genspider <爬虫实体名> <要爬虫的域名>
-
先看看能不能爬取,如果不能爬取,我们把君子协议关掉,在 settings注释掉
-
现在items.py文件里创建一个对象,并注明其属性
eg: class MyspiderDemonstrateDangdangwangItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() book_src = scrapy.Field() book_name = scrapy.Field() book_price = scrapy.Field()
-
先在爬虫文件里引入items.py
from myspider_demonstrate_dangdangwang.items import MyspiderDemonstrateDangdangwangItem
这个可能会报错,但不用管
-
根据网页的结构提取想要的信息,并使用
response.xpath()
方法提取需要的信息response.xpath()使用方法: 一般要爬取的数据都是重复的结构中,记得先循环提取再把里面需要的各个元素(如标题,图片)分别提取
eg: def parse(self, response): # li_list = response.xpath('//ul[@id="component_59"]/li') # # for li in li_list: # src = li.xpath('.//img/@data-original').extract_first() # # 第一张图片和其他的图片的标签的属性是不一样的 # # 第一张图片的src是可以使用的 其他的图片的地址是data-original # if src: # src = src # else: # # src = li.xpath('.//img/@src').extract_first() # print("没有图片") # print(src) # name = li.xpath('.//img/@alt').extract_first() # price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first() book_xpath_list = response.xpath('//ul[@id="component_59"]/li') for book in book_xpath_list: book_name = book.xpath('./a/@title').get() book_price = book.xpath('.//p[@class="price"]/span[1]/text()').extract_first() book_src = book.xpath('.//img/@data-original').get() if book_src: book_src = book_src else : book_src = book.xpath('.//img/@src').get() # print(book_price) bookall = MyspiderDemonstrateDangdangwangItem(book_src = book_src,book_name = book_name,book_price = book_price) # item就是yield返回的对象 yield bookall
-
在管道文件中(pipelines.py)设置,进行数据的清洗和文件的写入
文件打开要在爬虫前,避免重复打开你和关闭文件,爬虫开启前的函数:
def open_spider(self,spider):
;爬虫结束函数:def close_spider(self,spider):
在
def process_item(self, item, spider):
函数中进行文件写入eg: class MyspiderDemonstrateDangdangwangPipeline: # def process_item(self, item, spider): # with open('book.json', 'a', encoding='utf-8') as f: # f.write(str(item)+'\n') # return item def open_spider(self,spider): self.fp = open('book.json','w',encoding='utf-8') def process_item(self, item, spider): self.fp.write(str(item)) return item def close_spider(self,spider): self.fp.close()
-
开启多管道:
-
先在settings文件中,创建新管道类并设置优先级,优先级1-1000 值越小优先级越高
-
再在管道文件里创建新的类(当然名字要对应上),执行你想执行的操作,下面的例子是下载爬取url对应的图片
class DangDangImgDownload: def download_image(self,url, save_path): response = requests.get(url) if response.status_code == 200: with open(save_path, 'wb') as file: file.write(response.content) print(f"Image downloaded successfully and saved at: {save_path}") else: print(f"Failed to download image. Status code: {response.status_code}") def process_item(self,item,spider): # 你的图片URL # image_url = "https://img3m6.ddimg.cn/72/20/29420496-1_b_3.jpg" # # 保存图片的路径和文件名 # save_path = "C://Users//Carrot//Desktop//img11111.jpg" image_url = 'https:' + item['book_src'] # 保存图片的路径和文件名 save_path = 'D://pythonprojectlist//project4//myspider_demonstrate_dangdangwang//myspider_demonstrate_dangdangwang//spiders//bookimg//' + item['book_name'] + '.jpg' # 调用下载函数 self.download_image(image_url, save_path)
-
-
多页爬取
-
因为每一页要爬取的内容是一样的,所以只需要将每次url地址进行修改便可,一般url多页都会是有一个baseurl,后面跟着一个page的页码
base_url = 'https://search.dangdang.com/?key=%E9%9D%92%E6%98%A5&act=input&page_index=' page = 1
-
然后我们只需要进行循环,对page++便可,并拼接新的url,并使用
scrapy.Request(url=url,callback=self.parse)
进行请求便可if self.page < 100: self.page = self.page + 1 url = self.base_url + str(self.page) #scray.Request就是scrapy的get请求 #url就是请求地址 #callback是你要执行的那个函数 注意不需要加() yield scrapy.Request(url=url,callback=self.parse)
-
到这里基本关于文字和图片的爬取,无论是简单爬虫和使用scrapy框架的都基本介绍完毕,为了让大家学习和使用更方便,我也把上面这个爬取xx网的例子的代码上传到git里了