URL的组成 URL地址由协议头、服务器地址、文件路径三部分组成
协议头(Protocol Head) 协议头指定使用的传输协议,用于告诉浏览器如何处理将要打开的文件。不同的协议表示不同的资源查找以及传输方式。网络上常用的协议如表1所示。
表1 URL常见的协议
服务器地址(Hostname或者IP)和端口(Port) 
路径(Path) 路径是由0或者多个“/”符号隔开的字符串,一般用于指定本次请求的资源在服务器中的位置。
爬取第一个网站 目标网站: 百度首页
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import  urllib.requesturl = "https://www.baidu.com/"  headers = {     "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 "                    "Safari/537.36"  } request = urllib.request.Request(url=url, headers=headers) response = urllib.request.urlopen(request) content = response.read().decode("utf-8" ) print (response.getcode())
结果:
常见http状态码 https://www.runoob.com/http/http-status-codes.html 
Post请求百度翻译 
构建请求对象即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import  urllib.requestimport  urllib.parseimport  jsonurl = 'https://fanyi.baidu.com/sug'  data = {     'kw' : 'hello' , } headers = {     'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 '                    'Safari/537.36'  } data = urllib.parse.urlencode(data).encode('utf-8' ) request = urllib.request.Request(url=url, data=data, headers=headers) response = urllib.request.urlopen(request) res = response.read().decode() res = json.loads(res) print (res)
运行结果
 
爬取指定城市肯德基的相关信息 代码如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import  urllib.requestimport  urllib.parseimport  jsondef  create_request (page ):    """      创建请求对象     :param page: 页码     :return:  请求对象     """     baseurl = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=cname'      data = {         'cname' : '柳州' ,         'pid' : '' ,         'pageIndex' : page,         'pageSize' : '10' ,     }     data = urllib.parse.urlencode(data).encode('utf-8' )     headers = {         'Cookie' : '自己的Cookie' ,         'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '                        'Chrome/114.0.0.0 Safari/537.36'      }     request = urllib.request.Request(url=baseurl, data=data, headers=headers)     return  request def  get_content (request ):    response = urllib.request.urlopen(request)     content = response.read().decode('utf-8' )     return  content def  down_load (page, content ):    with  open ('D:/project_code_file/python/pythonSpider/data/'  + '柳州肯德基_'  + str (page) + '.json' , 'w' , encoding='utf-8' ) as  f:         f.write(content) if  __name__ == '__main__' :    start_page = int (input ('请输入起始页码:' ))     end_page = int (input ('请输入终止页码:' ))     for  page in  range (start_page, end_page + 1 ):         request = create_request(page)         content = get_content(request)         down_load(page, content) 
结果:
Cookie的简单使用 cookie简介 Cookie 是通过浏览器将服务器返回的数据保存在本地的一小块数据(一般小于4kb)。当浏览器发送请求且浏览器存在 Cookie 时,浏览器会自动在请求头携带上 Cookie 数据。引入 Cookie 的意义是因为 HTTP 的请求是无状态的,如:浏览器发出的请求服务器没办法区分浏览器用户身份以及用户的相关操作状态(可以通过 Cookie 传递这些信息)。最开始 Cookie 被作为唯一的存储手段,但是因为浏览器的每次请求都会携带上 Cookie,会带来额外的开销,而且存储量比较小,所以后来浏览器推出了新的 Api(web stoeage Api和 indexedDb)。
cookie使用场景 
会话状态管理(如用户登录状态、及其他需要记录的信息) 
个性化设置(如用户自定义设置) 
浏览器追踪行为(如追踪分析用户行为) 
 
实例 使用cookie进入微博登录状态的页面(获取的cookie是以及登录过微博之后的cookie)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 import  urllib.requestimport  urllib.parseurl = 'https://weibo.com/u/5887067753'  headers = {                         'Cookie' : '自己的Cookie' ,     'Referer' : 'https://weibo.com/set/index' ,                                             'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 '                    'Safari/537.36' ,           } request = urllib.request.Request(url=url, headers=headers) response = urllib.request.urlopen(request) content = response.read().decode('gb2312' ) with  open ('D:/project_code_file/python/pythonSpider/html/weibo.html' , 'w' , encoding='gb2312' ) as  fp:    fp.write(content) 
效果:
代理服务器 代理的常用功能 
突破自身ip的访问限制,访问国外站点 
访问一些单位或团体内部资源 
提高访问速度 
隐藏真实ip 
 
代码配置代理 
创建Reuqest对象 
创建ProxyHandler对象 
用handler对象创建opener对象 
使用opener.open函数发送请求 
 
实例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import  urllib.requesturl = 'https://www.baidu.com/s?ie=UTF-8&wd=ip'  headers = {     'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 '                    'Safari/537.36'  } proxies = {     'http' : 'ip:port' , } request = urllib.request.Request(url=url, headers=headers) handler = urllib.request.ProxyHandler(proxies=proxies) opener = urllib.request.build_opener(handler) response = opener.open (request) content = response.read().decode('utf-8' ) with  open ('D:/project_code_file/python/pythonSpider/html/ip.html' , 'w' , encoding='utf-8' ) as  fp:    fp.write(content) 
Xpath的简单使用 
使用到的python模块为lxml,一般是:from lxml import etree 
结合浏览器插件:XPath Helper使用(具体安装自己查),元素定位很方便,敏感肌也能用 
 
 
长这样:
虽然有XPath Helper,基本语法还是需要学一学的 
 
 
下面针对这个html文件,进行简单的使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <!DOCTYPE html > <html  lang ="en" > <head >     <meta  charset ="UTF-8" />      <title > Title</title >  </head > <body >     <ul >          <li  id  = "l1"  class ="c1" > 百度</li >          <li  id  = "l2" > 谷歌</li >          <li  id  = "c3" > 必应</li >          <li  id  = "c4" > 搜狗</li >      </ul >      <ul >          <li  id  = "l3" > 北京</li >          <li  id  = "l4" > 上海</li >          <li > 广州</li >          <li > 深圳</li >      </ul >  </body > </html > 
python代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 from  lxml import  etreetree = etree.parse('D:/project_code_file/python/pythonSpider/html/17xpath的基本使用.html' ) li_list = tree.xpath('//body//li/text()' ) print (li_list)li_list = tree.xpath('//li[@id]/text()' ) print (li_list)li_list = tree.xpath('//li[@id="l1"]/text()' ) print (li_list)li_list = tree.xpath('//li[@id="l1"]/@class' ) print (li_list)li_list = tree.xpath('//li[contains(@id,"l")]/text()' ) print (li_list)
requests模块的使用 简介 一个类型,六个属性
设置响应的编码格式:response.encoding = ‘编码格式’ 
返回网页内容:response.text 
返回网页的url:response.url 
返回网页的二进制数据:response.content 
返回响应头:response.headers 
 
get请求简单示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import  requestsurl = 'https://www.baidu.com/s?'  headers = { 	     'Cookie' : 'Cookie' ,     'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 '                    'Safari/537.36' , } data = {     'wd' : '北京'  } response = requests.get(url=url, params=data, headers=headers) response.encoding = 'utf-8'  response_text = response.text print (response_text)
post请求简单示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import  requestsimport  jsonurl = 'https://fanyi.baidu.com/sug'  headers = {     'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '                    'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36'  } data = {     'kw' : 'eye'  } response = requests.post(url=url, data=data, headers=headers) content = response.text dict_content = json.loads(content) print (dict_content)
综合案例(登录古诗文网) 
抓取登录接口常用方法:打开目标网站的登录界面>>>F12>>>Network>>>在网页输入错误的密码并且登录>>>找登录接口>>>分析 
 
 
开始干活:分析Form Data的数据,第一个__VIEWSTATE和第二份__VIEWSTATEGENERATOR数据看不懂,不知道哪里来的,先不着急,往下看,from应该是固定的,这个没问题,再往下看,只有code是随机的,那我们要怎样获取code呢?很简单,验证码是在网页中的,那我们把这张图片弄到手解析不就完了? 
 
 
这下好了,验证码的URL有了,还愁获取不到验证码信息吗!再来解决数据1和数据2的问题,一般这种找不到的信息都在网页源码当中ctrl f自己找一找看看 
 
 
简单示例, 没有使用到验证码图片解析,是比较笨的用手输入的,学过的朋友可以自己写一个来用 
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import  requestsfrom  bs4 import  BeautifulSouppost_url = 'https://so.gushiwen.cn/user/login.aspx?from=http%3a%2f%2fso.gushiwen.cn%2fuser%2fcollect.aspx'  url = 'https://so.gushiwen.cn/user/login.aspx?from=http://so.gushiwen.cn/user/collect.aspx'  code_url = 'https://so.gushiwen.cn/RandCode.ashx'  headers = {     'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 '                    'Safari/537.36'  } response = requests.get(url=url, headers=headers) content = response.text soup = BeautifulSoup(content, 'lxml' ) viewstate = soup.select('#__VIEWSTATE' )[0 ].attrs.get('value' ) viewstategenerator = soup.select('#__VIEWSTATEGENERATOR' )[0 ].attrs.get('value' ) session = requests.session() content_code = session.get(url=code_url, headers=headers).content with  open ('D:\project_code_file\python\pythonSpider\img\code.jpg' , 'wb' ) as  f:    f.write(content_code) code = input ("请输入验证码:" ) post_data = {     '__VIEWSTATE' : viewstate,     '__VIEWSTATEGENERATOR' : viewstategenerator,     'from' : 'http://so.gushiwen.cn/user/collect.aspx' ,     'email' : 'your email' ,     'pwd' : 'your passwd' ,     'code' : code,     'denglu' : '登录'  } response_post = session.post(url=post_url, headers=headers, data=post_data) content_post = response_post.text with  open ('D:\project_code_file\python\pythonSpider\html\gushiwen.html' , 'w' , encoding='utf-8' ) as  f:    f.write(content_post) 
selenium模块的使用 简介 
Selenium 是一种开源工具,用于在 Web 浏览器上执行自动化测试(使用任何 Web 浏览器进行 Web 应用程序测试)
 
环境准备 
需要对应的浏览器驱动,这里使用的是chromedriverchromedriver.exe 点我获取驱动  
驱动直接拖入项目文件夹下,放在别处要注意编码时的路径 
 
 
需求 
访问百度,并且在百度的搜索框上输入“周杰伦”,并且点击搜索按钮执行该操作
 
编码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from  selenium import  webdriverfrom  selenium.webdriver.chrome.options import  Optionsdef  share_chrome ():    chrome_options = Options()     chrome_options.add_argument('--headless' )     chrome_options.add_argument('--disable-gpu' )     path = r'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe'      chrome_options.binary_location = path     browser = webdriver.Chrome(chrome_options=chrome_options)     return  browser url = 'https://www.baidu.com'  browser = share_chrome() browser.get(url) text = browser.find_element_by_id('kw' ) text.send_keys('周杰伦' ) btn = browser.find_element_by_id('su' ) btn.click() sleep(2 ) browser.save_screenshot('baidu.png' ) 
说明 
此过程是隐式的。如何证明已经完成了此过程?具体可以看第29-30行代码
 
scrapy爬虫框架入门 简介 
scrapy是什么? 
 
scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。可以应用在包括数据挖掘、信息采集、等方面 
 
scrapy的安装 
 
pip install scrapy 
如果出现错误,十有八九应该是没配置twisted的问题 
 
scrapy项目的创建 
 
 
scrapy startproject 项目名(不能以数字开头,也不能包含中文)
创建爬虫文件,要在项目的spiders文件夹下创建爬虫文件 
 
 
cd .\项目名称\项目名称\spiders
scrapy genspider 爬虫文件的名字(不用带.py后缀) 爬取网站的域名
 
scrapy crawl 爬虫文件的名字
注意:要在spiders文件夹下执行
 
scrapy_demo	项目的名字
scrapy_demo	项目的名字,也是python软件包init .pyinit .py
 
scrapy框架结构 
scrapy引擎  
自动运行,不用管
scrapy下载器  
引擎给到对象和数据,并履行数据下载的职责
spiders  
spiders类定义了如何爬取某个网站,包括了爬取的方式,以及如何从网页的内容中提取结构化数据。换句话说,spiders是我们定义爬取动作以及分析某个网页的地方
scrapy 调度器  
爬虫框架的系统调度,不用管
scrapy管道  
最终处理数据的管道,会预留接口供我们处理数据
工作原理  
爬虫文件中常用的方法、属性 
首先核心爬虫文件中最核心的东西我个人觉得应该是response对象,response对象中包含了爬取网页的所有信息。获取自己想要的数据,就得熟悉该对象的属性还有方法
常用属性 
 
response.body 获取响应体,二进制数据 
response.text	获取响应体的文本 
response.url	获取url 
response.status	获取响应状态码 
response.encoding 获取响应体的编码 
response.request 获取请求对象 
response.headers 获取响应头 
 
常用方法 
 
response.xpath(xpath路径)	使用xpath路径查询特定元素,返回一个selector列表对象 
 
 
selector对象中常用的有extract()方法,该方法可以提取selector对象的值,使用xpath请求到的对象是一个selector对象,需要进一步使用extract()方法拆解成unicode字符串。同样的,常用的还有extract_first()方法,见名知意,该方法会提取selector对象中的第一个值。需要注意的是,每一个selector对象可以多次调用xpath方法。
yield 
 
带有 yield 的函数不再是一个普通函数,而是一个生成器generator,可用于迭代 
yield 是一个类似 return 的关键字,迭代一次遇到yield时就返回yield后面(右边)的值。重点是:下一次迭代 时,从上一次迭代遇到的yield后面的代码(下一行)开始执行 
简要理解:yield就是 return 返回一个值,并且记住这个返回的位置,下次迭代就从这个位置后(下一行)开始 
 
 
案例(当当网) 需求 
获取该网页书的图片还有书名、价格https://category.dangdang.com/cp01.01.02.00.00.00.html 
 
操作步骤 
dangdang.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import  scrapyfrom  scrapy_dangdang_41.items import  ScrapyDangdang41Itemclass  DangdangSpider (scrapy.Spider):    name = 'dangdang'           allowed_domains = ['category.dangdang.com' ]     start_urls = ['https://category.dangdang.com/cp01.01.02.00.00.00.html' ]     base_url = 'https://category.dangdang.com/pg'      page_num = 1      tail_url = '-cp01.01.02.00.00.00.html'      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()             if  src:                 src = src             else :                 src = li.xpath('.//img/@src' ).extract_first()             name = li.xpath('.//img/@alt' ).extract_first()             price = li.xpath('.//p[@class="price"]/span[1]/text()' ).extract_first()             book = ScrapyDangdang41Item(src=src, name=name, price=price)             yield  book           if  self .page_num < 100 :             self .page_num += 1              url = self .base_url + str (self .page_num) + self .tail_url                                                                 yield  scrapy.Request(url=url, callback=self .parse) 
items.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import  scrapyclass  ScrapyDangdang41Item (scrapy.Item):                   src = scrapy.Field()       name = scrapy.Field()       price = scrapy.Field()   
pipelines.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 from  itemadapter import  ItemAdapterimport  requestsclass  ScrapyDangdang41Pipeline :         def  open_spider (self, spider ):         print ('爬虫开始了' )         self .fp = open ('D:\\project_code_file\\python\\pythonSpider\\data\\book.json' , 'w' , encoding='utf-8' )     def  process_item (self, item, spider ):                                                               self .fp.write(str (item) + '\n' )         return  item     def  close_spider (self, spider ):         print ('爬虫结束了' )         self .fp.close() class  DangDangDownloadPipeline :    def  process_item (self, item, spider ):                  src = "http:"  + item['src' ]                  res = requests.get(src)                  img_data = res.content                  img_name = item['name' ] + '.jpg'                   img_path = 'D:\\project_code_file\\python\\pythonSpider\\img\\books\\'  + img_name                  with  open (img_path, 'wb' ) as  f:             f.write(img_data)         return  item 
settings.py
把管道开启,并且把ROBOTSTXT_OBEY注释掉,或者设置为False即可
 
1 2 3 4 5 6 7 ITEM_PIPELINES = {          'scrapy_dangdang_41.pipelines.ScrapyDangdang41Pipeline' : 300 ,     'scrapy_dangdang_41.pipelines.DangDangDownloadPipeline' : 301 , } 
运行项目(注意一定要在项目的spiders目录下执行该命令!)
scrapy crawl dangdang
 
 
 
结果:(还没爬完…..做个测试即可) CrawlSpider 简介 
 继承自scrapy.Spider
 
链接提取器 1 2 3 4 scrapy.linkextractors.LinkExtractor(     allow = (正则表达式 提取符合正则的链接)     restrict_xpaths = (xpath, 提取符合xpath规则的链接) ) 
使用样例 
正则: link = LinkExtractor(allow=r’正则表达式’) 
xpath:link = LinkExtractor(restrict_xpaths=r’xpath表达式’) 
 
提取链接 link.extract_links(response)
注意事项 follow = bool
案例(CrawlSpider 读书网) 需求 读书网数据入库,使用到mysql数据库
操作步骤 
创建项目
 scrapy startproject scrapy_readbook_43
 
跳转到spiders目录下
cd .\scrapy_readbook_43\scrapy_readbook_43\spiders
 
创建爬虫文件
scrapy  gensipder -t crawl readbook www.dushu.com 
 
编码
 
readbook.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import  scrapyfrom  scrapy.linkextractors import  LinkExtractorfrom  scrapy.spiders import  CrawlSpider, Rulefrom  scrapy_readbook_43.items import  ScrapyReadbook43Itemclass  ReadbookSpider (CrawlSpider ):    name = 'readbook'      allowed_domains = ['www.dushu.com' ]     start_urls = ['https://www.dushu.com/book/1188_1.html' ]     rules = (         Rule(LinkExtractor(allow=r'/book/1188_\d+\.html' ), callback='parse_item' , follow=True ),     )     def  parse_item (self, response ):         img_list = response.xpath('//div[@class="bookslist"]//img' )         author_list = response.xpath('//div[@class="book-info"]/p[1]/text()' ).extract()         i = 0          for  img in  img_list:             photo_url = img.xpath('./@data-original' ).extract_first()             book_name = img.xpath('./@alt' ).extract_first()             author = author_list[i]             i += 1              book = ScrapyReadbook43Item(photo_url=photo_url, book_name=book_name, author=author)             yield  book 
items.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import  scrapyclass  ScrapyReadbook43Item (scrapy.Item):                   photo_url = scrapy.Field()     book_name = scrapy.Field()     author = scrapy.Field() 
pipelines.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 from  itemadapter import  ItemAdapterfrom  pymysql import  Connectionclass  ScrapyReadbook43Pipeline :    def  open_spider (self, spider ):         self .fp = open ('readbook.json' , 'w' , encoding='utf-8' )     def  process_item (self, item, spider ):         self .fp.write(str (item) + '\n' )         return  item     def  close_spider (self, spider ):         self .fp.close() class  MysqlPipeline :    def  __init__ (self ):         self .cursor = None          self .connect = None      def  open_spider (self, spider ):         self .connect_database()     def  connect_database (self ):         self .connect = Connection(             host='localhost' ,             port=3306 ,             user='root' ,             password='123456' ,             autocommit=True ,                                   )         self .connect.select_db('spider01' )     def  process_item (self, item, spider ):         self .cursor = self .connect.cursor()         sql = "insert into books(book_name, author, photo_url) values('{}', '{}', '{}')" .format (item['book_name' ], item['author' ], item['photo_url' ])         self .cursor.execute(sql)         return  item     def  close_spider (self, spider ):         self .cursor.close()         self .connect.close()         print ("数据库连接关闭" ) 
settings.py
开启管道即可
 
1 2 3 4 5 6 ITEM_PIPELINES = {     'scrapy_readbook_43.pipelines.ScrapyReadbook43Pipeline' : 300 ,     'scrapy_readbook_43.pipelines.MysqlPipeline' : 301 , } 
在settings.py中也可以指定日志的显示形式LOG_FILE = '文件名.log'
结果 数据库
json文件