当前位置:   article > 正文

【爬虫2】——聚焦爬虫

聚焦爬虫

目录

 二、聚焦爬虫

步骤:

主要技术——数据解析:

编码实践

正则

        基础知识

        1.简单的爬取图片

        2.正式爬取图片                

        3.正式爬取图片(2)     使用os

        4.正式爬取图片(3)    分页爬取

bs4

原理:

基础知识

爬虫实践

1.爬目录

2.爬目录+详细内容

基础知识

 【实战1】——58同城二手房爬取

【实战2】——图片爬取

【实战3】——爬取免费简历模板


 二、聚焦爬虫

在通用爬虫基础上,爬取特定内容

所以,

步骤:

  1. 网址
  2. 请求
  3. 获取数据
  4. 数据解析
  5. 存数据

主要技术——数据解析

解析的局部文本内容都在标签之间或者属性中存储

所以,大象塞冰箱里,2步:

  1. 定位标签
  2. 标签内容或者属性中存储的数据进行提取(解析)

分类:

  • 正则
  • bs4
  • xpath

编码实践

  • 正则

        基础知识

 

 

 

 

 

 

 

        1.简单的爬取图片
  1. import requests
  2. if __name__ == "__main__":
  3. headers = {
  4. "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"
  5. }
  6. url = 'https://img-blog.csdnimg.cn/88f0581db75245a198deba3b1bad2e60.png'
  7. # content返回二进制形式的图片数据
  8. # json()对象 text字符串 content二进制
  9. img_content = requests.get(url=url,headers=headers).content
  10. with open('./img1.jpg','wb') as fp:
  11. fp.write(img_content)

        2.正式爬取图片                
  1. import re
  2. import requests
  3. if __name__ == "__main__":
  4. headers = {
  5. "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"
  6. }
  7. # 1.确定网址
  8. url = 'https://books.toscrape.com/'
  9. # 2.发请求,得到html
  10. html = requests.get(url=url,headers=headers).text
  11. # 3.分析html结构,用正则进行数据解析
  12. # < div class ="image_container" >
  13. # < a href = "catalogue/tipping-the-velvet_999/index.html" >
  14. # < img src = "media/cache/26/0c/260c6ae16bce31c8f8c95daddd9f4a1c.jpg" alt = "Tipping the Velvet" class ="thumbnail" >
  15. # < / a >
  16. # < / div >
  17. html=html.replace('\n',' ')
  18. ex = '<div class="image_container">.*?<img src="(.*?)" alt.*?'#注意这里不要有多余的空格,直接黏贴确实会有空格,所以还要手动改改
  19. img_list=re.findall(ex,html)
  20. print(img_list)
  21. #4.链接完整的网址
  22. # https://books.toscrape.com/media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg
  23. # media/cache/2c/da/2cdad67c44b002e7ead0cc35693c0e8b.jpg
  24. for src in img_list:
  25. url='https://books.toscrape.com/'+src
  26. img_content=requests.get(url=url,headers=headers).content
  27. # 获取每个图片的名字
  28. # 通过/ 分割,并【-1】快速拿到最后一个 yyds
  29. fileName='./img/'+src.split('/')[-1]
  30. #./img/94b1b8b244bce9677c2f29ccc890d4d2.jpg
  31. with open(fileName,'wb') as fp:
  32. fp.write(img_content)
  33. print(fileName+'保存成功!!!')

        3.正式爬取图片(2)     使用os
  1. import os
  2. import re
  3. import requests
  4. if __name__ == "__main__":
  5. # 新增了!!!!!!
  6. if not os.path.exists('./img'):
  7. os.mkdir('./img')
  8. headers = {
  9. "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"
  10. }
  11. # 1.确定网址
  12. url = 'https://books.toscrape.com/'
  13. # 2.发请求,得到html
  14. html = requests.get(url=url,headers=headers).text
  15. # 3.分析html结构,用正则进行数据解析
  16. html = html.replace('\n', ' ')#没有这个换行也不行,因为.不匹配换行啊!!!!!
  17. ex = '<div class="image_container">.*?<img src="(.*?)" alt.*?'#注意这里不要有多余的空格,直接黏贴确实会有空格,所以还要手动改改
  18. img_list=re.findall(ex,html)
  19. print(img_list)
  20. #4.链接完整的网址
  21. for src in img_list:
  22. url='https://books.toscrape.com/'+src
  23. img_content=requests.get(url=url,headers=headers).content
  24. fileName='./img/'+src.split('/')[-1]
  25. with open(fileName,'wb') as fp:
  26. fp.write(img_content)
  27. print(fileName+'保存成功!!!')

        4.正式爬取图片(3)    分页爬取
  1. import os
  2. import re
  3. import requests
  4. if __name__ == "__main__":
  5. # os
  6. if not os.path.exists('./img'):
  7. os.mkdir('./img')
  8. headers = {
  9. "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"
  10. }
  11. # 我要分页爬取,所以重新确定网址
  12. # https://books.toscrape.com/catalogue/page-2.html
  13. # 分析出来,改参数就可以实现分页效果,所以,就循环喽
  14. for page_num in range(1,5):
  15. url = 'https://books.toscrape.com/catalogue/page-{:d}.html'.format(page_num)
  16. # print(url)
  17. # 2.发请求,得到html
  18. html = requests.get(url=url,headers=headers).text
  19. # 3.分析html结构,用正则进行数据解析
  20. html=html.replace('\n',' ')
  21. ex = '<div class="image_container">.*?<img src="(.*?)" alt.*?'#注意这里不要有多余的空格,直接黏贴确实会有空格,所以还要手动改改
  22. img_list=re.findall(ex,html)
  23. print(img_list)
  24. #4.链接完整的网址
  25. for src in img_list:
  26. url='https://books.toscrape.com/'+src
  27. img_content=requests.get(url=url,headers=headers).content
  28. fileName='./img/'+src.split('/')[-1]
  29. with open(fileName,'wb') as fp:
  30. fp.write(img_content)
  31. print(fileName+'保存成功!!!')

  • bs4

原理:
  1. 实例化一个BeautifulSoup对象,并将页面源码数据加载到该对象中
  2. 调用该对象的属性或方法,进行标签定位和数据提取 

BeautifulSoup(content, 'lxml')` 和 `BeautifulSoup(content, 'html.parser')` 都是使用 BeautifulSoup 库来解析 HTML 或 XML 内容的方式,但使用了不同的解析器。

区别如下:

1. 解析器:`lxml` 使用了第三方库 lxml 来解析 HTML 或 XML,而 `html.parser` 则使用 Python 内置的标准库 html.parser 来解析。
2. 性能:`lxml` 解析器通常比 `html.parser` 解析器更快,因为 lxml 是 C 语言编写的,而 html.parser 是纯 Python 实现的。因此,处理大型文档时,`lxml` 解析器可能更高效。
3. 容错性:`html.parser` 解析器在处理不规范的 HTML 或 XML 时更具容错性,能够处理一些不完全闭合标签或其他错误的情况。而 `lxml` 解析器对于不规范的文档可能会报错或产生不可预测的结果。
4. 功能:`lxml` 解析器提供了更多的功能和选项,例如 XPath 查询、CSS 选择器等。而 `html.parser` 解析器的功能较为简单,不支持这些高级功能。

选择使用哪个解析器取决于具体的需求和情况。如果处理的是规范的 HTML 或 XML,且需要更高的性能和功能,可以选择 `lxml` 解析器。如果处理的是不规范的文档,或者只需要基本的解析功能,可以选择 `html.parser` 解析器。

需要注意的是,使用 `lxml` 解析器需要先安装 lxml 库,可以通过 `pip install lxml` 命令进行安装。而 `html.parser` 解析器是 Python 的标准库,在大多数情况下无需额外安装。

基础知识
  1. # 一、对象的实例化
  2. # 本地实例化
  3. from bs4 import BeautifulSoup
  4. fp= open('./test.html','r',encoding='utf-8')
  5. soup=BeautifulSoup(fp,'html.parser')
  6. # 网上实例化
  7. # page_text=response.text
  8. # soup=BeautifulSoup(page_text,'html.parser')
  9. # 二、数据解析的方法和属性
  10. # 1.soup.tagName返回html中第一次出现的tagName标签
  11. print(soup.a)
  12. # 2.soup.find("tagName)等同于soup.div
  13. print(soup.find('a'))
  14. print(soup.find('div',class_='left'))
  15. # 3.返回符合要求的所有标签(列表)
  16. print(soup.findAll('a'))
  17. # 4.选择器,返回列表 id class 标签 ……
  18. print(soup.select('.left'))
  19. # >表示一个层级
  20. #空格表示多个层级
  21. print(soup.select('.left>ul>li'))
  22. # 三、获取标签之间文本数据
  23. soup.a.text soup.xxx.get_text()#获得所有内容,不是直系的内容也可以获得
  24. soup.xxxx.string #只能直系内容
  25. # 四、获取标签属性值
  26. # soup.select('.left a')['href'] 不可以
  27. print(soup.a['href'])

爬虫实践
1.爬目录
  1. import requests
  2. from bs4 import BeautifulSoup
  3. headers = {
  4. "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"
  5. }
  6. url='https://www.shicimingjv.com/bookindex/75.html'
  7. response=requests.get(url=url,headers=headers)
  8. print(response)
  9. html=response.text
  10. soup=BeautifulSoup(html,'html.parser')
  11. all_ul=soup.findAll('ul',class_='book-tags')
  12. all_title=soup.findAll('h4')
  13. # print(all_title)
  14. # print(all_ul)
  15. # for ul in all_ul:
  16. # all_li=ul.findAll('li')
  17. # # print(all_li)
  18. # for li in all_li:
  19. # print(li.text )
  20. # print("*****************")
  21. for i in range(len(all_ul)):
  22. print(all_title[i].text)
  23. # print(all_ul[i].text)
  24. # print(all_ul[i].findAll('li'))
  25. all_li=all_ul[i].findAll('li')
  26. for li in all_li:
  27. a=li.a
  28. #a=li.find('a')也可以
  29. print(a.text)
  30. print("________________________________________")
  31. #其实直接ul.text也行的 反正文字也没有别的了
2.爬目录+详细内容

这有点鸡肋,在详情页也可以爬到标题啊

  1. import requests
  2. from bs4 import BeautifulSoup
  3. headers = {
  4. "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"
  5. }
  6. url='https://www.shicimingjv.com/bookindex/78.html'
  7. response=requests.get(url=url,headers=headers)
  8. print(response)
  9. html=response.text
  10. soup=BeautifulSoup(html,'html.parser')
  11. # print(soup.a)
  12. # 1.爬取标题和超链接
  13. # 通过超链接再爬取详情页内容
  14. all_titles=soup.select('.book-tags li a')
  15. # print(all_titles)
  16. i=0
  17. for item in all_titles:
  18. url2=item['href']
  19. # print(url2)
  20. response2=requests.get(url=url2,headers=headers)
  21. html2=response2.text
  22. soup2=BeautifulSoup(html2,'html.parser')
  23. all_p = soup2.findAll('p')
  24. # 获取详细内容
  25. content=""
  26. for p in all_p:
  27. p = p.text.strip()
  28. content+=p+'\n'
  29. # print(content)
  30. #优化 一步搞定获取内容
  31. #content=soup2.find('div',class_='entry-content').text
  32. fileName=str(all_titles[i].text)
  33. filePath='./shangjunshu/'+fileName+'.txt'
  34. with open(filePath,'w',encoding='utf-8' ) as fp:
  35. fp.write(content)
  36. i+=1
  37. print(fileName+'succeed')
  • xpath

最常用、最便捷、通用性最好

解析原理:

  1. 实例化etree对象,讲页面源码数据加载到该对象中
  2. 调用该对象的xpath方法,结合xpath表达式,实现标签定位和内容捕获
基础知识
  1. # 实例化etree对象
  2. from lxml import etree
  3. # 本地
  4. etree.parse(filePath)
  5. # 互联网
  6. etree.HTML('page_text')
  1. from lxml import etree
  2. tree = etree.parse("hhh.html", etree.HTMLParser())
  3. # print(tree)
  4. # / 表示从根节点开始定位,表示一个层级
  5. r = tree.xpath('/html/head/title')
  6. # // 表示多个层级
  7. r = tree.xpath('/html//title')
  8. # // 表示从任意位置开始定位
  9. r = tree.xpath('//title')
  10. # 属性定位 tagName[@attrName="attrValue"
  11. r = tree.xpath('//div[@class="left"] ')
  12. # 索引定位 下标从1开始
  13. r = tree.xpath('//div[@class="left"]/ul[1] ')
  14. # 取出文本
  15. r = tree.xpath('//div[@class="left"]/ul[1]/li[2]/a/text() ') # ['love']
  16. r = tree.xpath('//div[@class="left"]/ul[1]/li[2]/a/text() ')[0] # love
  17. # /text()获取标签中直系的内容
  18. r = tree.xpath('//div[@class="left"]/ul[1]/li[2]/text() ') # 空,啥也没有,因为不是直系的文字
  19. # //text()非直系 所有文字
  20. r = tree.xpath('//div[@class="left"]/ul[1]/li[2]//text() ') #
  21. r = tree.xpath('//div[@class="left"]/ul[1]//text() ') #['wwwwww', 'love', '\r\n ']
  22. # 取属性 /@sttrName
  23. r = tree.xpath('//div[@class="right"]/img/@src ')
  24. 局部解析是./
  25. #或
  26. r = tree.xpath('//div[@class="left"]/ul/li/a | //div[@class="bottom"]/ul/div[2]/li/a')
  27. print(r)
 【实战1】——58同城二手房爬取
  1. from lxml import etree
  2. import requests
  3. # 1.爬取页面源码数据
  4. url = "https://dl.58.com/ershoufang/"
  5. headers = {
  6. # "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"
  7. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
  8. }
  9. # response=requests.get(url=url,headers=headers)
  10. # html=response.text
  11. # print(html)
  12. # with open('./58.html','w',encoding='utf-8') as fp:
  13. # fp.write(html)
  14. # 加上utf-8就不会是乱码了
  15. tree=etree.parse('./58.html',etree.HTMLParser(encoding='utf-8'))
  16. all_title=tree.xpath('//h3[@class="property-content-title-name"]/@title')
  17. all_detail=tree.xpath('//p[@class="property-content-info-text property-content-info-attribute"]//text()')
  18. all_totalPrice=tree.xpath('//p[@class="property-price-total"]//text()')
  19. fp=open('./house58.txt','w',encoding='utf-8')
  20. for i in range(0,len(all_title)):
  21. all_str=all_title[i]+"\n详情:"+str(all_detail[i*11:11+i*11])+"\n总价:"+str(all_totalPrice[i*3:3+i*3])
  22. all_str=all_str.replace('[','').replace(']','').replace('\'','').replace(" ",'').replace(",",'')
  23. all_str+='\n____________________________________________________________________________________\n'
  24. fp.write(all_str)
【实战2】——图片爬取
  1. from lxml import etree
  2. import requests
  3. headers = {
  4. # "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"
  5. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
  6. }
  7. for i in range(1,4):
  8. if i==1:
  9. url='http://pic.netbian.com/4kdongman'
  10. else:
  11. url='http://pic.netbian.com/4kdongman/index_{:d}.html'.format(i)
  12. print(url)
  13. response=requests.get(url=url,headers=headers)
  14. # 解决乱码 【方法一】 不好用
  15. response.encoding='utf-8'
  16. # 解决乱码 【方法二】 好用
  17. response.encoding='gbk'
  18. print(response)
  19. html=response.text
  20. # tree=etree.parse('./img_4k.html',etree.HTMLParser(encoding='utf-8'))
  21. tree=etree.HTML(html)
  22. all_src = tree.xpath('//ul[@class="clearfix"]/li/a/img/@src')
  23. all_name = tree.xpath('//ul[@class="clearfix"]/li/a/img/@alt')
  24. # print(all_name)
  25. # print(all_src)
  26. for j in range(len(all_src)):
  27. # http://pic.netbian.com/uploads/allimg/230602/002954-16856369943b94.jpg
  28. src="http://pic.netbian.com/"+all_src[j]
  29. fileName=str(i)+str(all_name[j])
  30. print(fileName)
  31. filePath = "./dongman_img/" + fileName + '.jpg'
  32. # 解决乱码 【方法三】 不好用
  33. # fileName=fileName.encode('iso-8859-1').decode('gbk')
  34. print(fileName)
  35. response2= requests.get(url=src,headers=headers)
  36. # 要用content返回二进制数据,别i+的都不行
  37. content=response2.content
  38. with open(filePath, 'wb') as fp:
  39. fp.write(content)
  40. print(fileName+'succeed!!!!')
  41. print("______________________________________________________")
【实战3】——爬取免费简历模板
  1. from lxml import etree
  2. import requests
  3. import re
  4. headers = {
  5. # "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"
  6. 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
  7. }
  8. fp=open('./jianli.txt','w',encoding='utf-8')
  9. url="https://sc.chinaz.com/jianli/free.html"
  10. response=requests.get(url=url,headers=headers)
  11. response.encoding='utf-8'
  12. print(response)
  13. html=response.text
  14. # 'gbk' 'utf-8' 'iso-8859-1'
  15. # with open('./jianli.html','w',encoding='iso-8859-1') as fp:
  16. # fp.write(html)
  17. # encoding='gbk'就什么都解析不出来
  18. # iso-8859-1 就是乱码
  19. # 响应内容的实际编码与 response.encoding 不匹配,可能会导致乱码问题
  20. # tree=etree.parse('./jianli.html',etree.HTMLParser(encoding='utf-8'))
  21. tree=etree.HTML(html)
  22. # 获取总页数
  23. all_page=tree.xpath('//div[@class="pagination fr clearfix clear"]/a/@href')
  24. print(all_page)
  25. page_li=[]
  26. for i in all_page:
  27. page_num=re.findall("free_(\d{1,}).html",i)
  28. # print(page_num)
  29. page_li.append(page_num)
  30. max_page_num=max(page_li)
  31. print(max_page_num)
  32. # 为了避免内存爆了,就先爬3页
  33. page=3
  34. # 爬每一页
  35. for page in range(1,4):
  36. if page==1:
  37. url="https://sc.chinaz.com/jianli/free.html"
  38. else:
  39. url="https://sc.chinaz.com/jianli/free_{:d}.html".format(page)
  40. print(url)
  41. response_page = requests.get(url=url, headers=headers)
  42. response_page.encoding = 'utf-8'
  43. # print(response_page)
  44. page_html = response_page.text
  45. page_tree=etree.HTML(page_html)
  46. all_href=page_tree.xpath('//div[@class="box col3 ws_block"]/a/@href')
  47. # 爬取详情页面
  48. for i in range(len(all_href)):
  49. url2=all_href[i]
  50. response_detail=requests.get(url=url2,headers=headers)
  51. response_detail.encoding='utf-8'
  52. # print(response_detail)
  53. detail_html=response_detail.text
  54. # with open('./detailHTML.html','w',encoding='iso-8859-1') as fp:
  55. # fp.write(detail_html)
  56. detail_tree=etree.HTML(detail_html,etree.HTMLParser(encoding='utf-8'))
  57. all_download_href=detail_tree.xpath('//div[@class="clearfix mt20 downlist"]/ul/li/a/@href')
  58. download_name= str(detail_tree.xpath('//div[@class="ppt_tit clearfix"]/h1/text()')[0] )
  59. # print(download_name)
  60. content=download_name+" 福建电信下载链接:"+all_download_href[0]+'\n\n'
  61. fp.write(content)
  62. print(download_name+" 福建电信下载链接:"+all_download_href[0])
  63. print("\n___________________________________________________________________________\n")
  64. fp.close()

 

 写文章-CSDN博客

Pycharm快捷键:

ctrl+Alt+L 代码格式化

shift+tab   取消缩进

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/495325
推荐阅读
相关标签
  

闽ICP备14008679号