python爬虫入门

Posted 临风而眠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python爬虫入门相关的知识,希望对你有一定的参考价值。

python爬虫入门(4)

​ bs4库实践

一.信息组织与提取方法

1.三种主要的信息组织形式

XML JSON YAML

image-20210711223004899

image-20210711213055127

image-20210711213025838

2.信息提取的一般方法

​ 从标记过的信息中提取所关注的内容

image-20210711213454113 image-20210711213519925 image-20210711213554093

实例:提取html中所有URL链接

方法:

(1)搜索到所有<a>标签

(2)解析<a>标签格式,提取href后的链接内容

import requests
from bs4 import BeautifulSoup
r = requests.get("http://python123.io/ws/demo.html")
demo =r.text
soup = BeautifulSoup(demo,"html.parser")
for link in soup.find_all('a'):
    print(link.get('href'))

运行结果

http://www.icourse163.org/course/BIT-268001
http://www.icourse163.org/course/BIT-1001870001

3.基于bs4库的HTML内容查找方法

find_all方法

image-20210711222414275

name参数
import requests
from bs4 import BeautifulSoup
r = requests.get("http://python123.io/ws/demo.html")
demo =r.text
soup = BeautifulSoup(demo,"html.parser")
print(soup.find_all('a'))
print(soup.find_all(['a','b']))

运行结果

[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]
[<b>The demo python introduces several python courses.</b>, <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]
for tag in soup.find_all(True):
    print(tag.name)

运行结果

html
head
title
body
p
b
p
a
a
attrs参数
print(soup.find_all('p','course'))
print(soup.find_all(id='link1'))

运行结果

[<p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>.</p>]
[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>]
import re
import requests
from bs4 import BeautifulSoup
r = requests.get("http://python123.io/ws/demo.html")
demo =r.text
soup = BeautifulSoup(demo,"html.parser")
print(soup.find_all(id=re.compile('link')))

​ 这里用到了正则表达式,会输出id以link开头的信息

运行结果

[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic 
Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]
recursive参数

默认True,若想只搜索儿子节点,就设置为False

print(soup.find_all('a'))
print(soup.find_all('a',recursive=False))#仅搜索儿子节点
string参数
print(soup.find_all(string="Basic Python"))
print(soup.find_all(string=re.compile("python")))#正则表达式

运行结果

['Basic Python']
['This is a python demo page', 'The demo python introduces several python courses.']

由于find_all很常用,故提供了两种简单的等价形式

image-20210711222528829

image-20210711222703258

二.实例:爬取菜价

​ 爬取北京新发地市场上的菜价信息

image-20210717180033355

1.查看网页源代码

​ 查看源代码,看源代码中是否直接显示需要爬取的信息

image-20210717180235147

​ 发现有,进行下一步

2.检验状态码

import  requests
url="http://www.xinfadi.com.cn/marketanalysis/0/list/1.shtml"
resp=requests.get(url)
print(resp.status_code)

返回值为200,可以正常访问

爬取网页源代码

print(resp.text)

中文可以正常显示,字符集没有问题

3.生成Beautiful对象

​ 不要忘记解释器

#指定html解析器
page=BeautifulSoup(resp.text,"html.parser")

4.查找数据(菜价表)

​ 方法:

find(标签,属性=属性值) (find只找一个)

find_all

​ 所找内容在一个表格里面,先找<table>

有很多<table>标签,他们的不同就是class属性的属性值不同

image-20210717181311058

#find方法
table=page.find("table",class_="hq_table")

因为class是python的关键字,所以易混淆,bs4提供了加一个下划线的方法来区分

另一种写法:

table=page.find("table",attrs={"class":"hq_table"})

​ 此写法避免class问题

5.在菜价表里找具体数据

<tr>代表行

<td>代表列

image-20210717235045544

图中所显示的是第一个<tr>标签出现的地方

而后面第二个<tr>标签开始才是正式的所要提取的内容

image-20210718000355474

要在每个<tr>标签里找到所有<td>标签,分别对应品名,最低价,平均价,最高价,规格,单位,发布日期

具体代码如下:

trs=table.find_all("tr")[1:]#第一行表头先不提取
for tr in trs:#每一行
    tds=tr.find_all("td")
    # .text表示拿到被标签标记的内容
    name =tds[0].text  #品名
    lowest =tds[1].text #最低价
    mean =tds[2].text #平均价
    highest=tds[3].text #最高价
    guige =tds[4].text #规格
    unit =tds[5].text #单位
    date =tds[6].text #发布日期
    print(name,lowest,mean,highest,guige,unit,date)

​ python语法没过关, 🌵🐶,去搜了个python切片的教程

6.写入文件

import csv
f=open("菜价.csv",mode="w")
csvwriter = csv.writer(f)

7.完整代码

#爬取菜价
import  requests
from bs4 import  BeautifulSoup
import csv
url="http://www.xinfadi.com.cn/marketanalysis/0/list/1.shtml"
resp=requests.get(url)
#指定html解析器
page=BeautifulSoup(resp.text,"html.parser")
# table=page.find("table",class_="hq_table")
f=open("菜价.csv",mode="w")
csvwriter = csv.writer(f)

table=page.find("table",attrs={"class":"hq_table"})
#拿到每一行的数据
trs=table.find_all("tr")[1:]#第一行表头先不提取
for tr in trs:#每一行
    tds=tr.find_all("td")
    # .text表示拿到被标签标记的内容
    name =tds[0].text  #品名
    lowest =tds[1].text #最低价
    mean =tds[2].text #平均价
    highest=tds[3].text #最高价
    guige =tds[4].text #规格
    unit =tds[5].text #单位
    date =tds[6].text #发布日期
    csvwriter.writerow([name,lowest,mean,highest,guige,unit,date])

f.close()
print("done!")
resp.close()

三.实例:爬取图片

​ 目标,在优美图库网站上爬取动画图片

image-20210718165558795

1.查看网页源码

​ 所要爬取的是具体的图片,首先看所需爬取内容是否在源码中有体现

image-20210718165718067

​ 比如第一张双刀索隆,是有的,那就可以继续了

2.查看状态码,编码

import requests
from bs4 import BeautifulSoup

url = "https://umei.net/katongdongman/"
resp = requests.get(url)
print(resp.status_code)
print(resp.apparent_encoding)
print(resp.encoding)

状态码是200
resp.apparent_encodingutf-8
resp.encodingISO-8859-1

所以需要修改编码

resp.encoding=resp.apparent_encoding

​ 检验编码除了上面那种打印两种编码对比是否相同的方法,还可以先print(resp.text),然后看是否有乱码,有乱码就去看charset里面写的编码,然后把resp.encoding改为那种编码即可

3.生成Beautiful对象

mainpage = BeautifulSoup(resp.text, "html.parser")

4.在主页面找到分区

image-20210718231651838

​ 找到有辨识度网页源码,ctrl+F搜索发现网页源码中只有这一处有

TypeList,所以可以选择这个

ChildPages = mainpage.find("div", attrs={"class": "TypeList"})

5.拿到各个所需图片的所在网址的url

childs = ChildPages.find_all("a")#find_all方法会返回一个列表
for child in childs:
    # 从BeautifulSoup对象拿到里面的href属性的值,直接用get
    print(child.get("href"))

image-20210718232717100

发现不是完整的域名,要拼接一下

for child in childs:
    # 从BeautifulSoup对象拿到里面的href属性的值,直接用get
    # print(child.get("href"))

    child_page_resp = requests.get("https://umei.net/"+child.get("href"))
    child_page_resp.encoding = 'utf-8'
    child_page_text = child_page_resp.text
    

6.在各个子页面找图片的下载地址

以双刀索隆那张图为例,在那个子页面找辨识度高的源代码

image-20210718234643760

for child in childs:
    # 从BeautifulSoup对象拿到里面的href属性的值,直接用get
    # print(child.get("href"))

    child_page_resp = requests.get("https://umei.net/"+child.get("href"))
    child_page_resp.encoding = 'utf-8'
    child_page_text = child_page_resp.text

    child_page = BeautifulSoup(child_page_text,"html.parser")
    p=child_page.find("p",align="center")
    img =p.find("img")
    print(img)
    break
    #先试一下效果,所以加一个break

成功!

image-20210718235101931

​ 实际需要的是src属性

在标签里面拿到属性,用.get()方法

	print(img.get("src"))

7.下载图片

​ 请求图片的地址即可

	img = p.find("img")
 	   src = img.get("src")

  	  # 下载图片
  	  img_resp = requests.get(src)
  	  img_name = src.split("/")[-1]
   	 # 拿到url中的最后一个/后面的内容
   	  with open("picture/"+img_name, mode="wb")as f:  # 放	在提前建好的picture文件夹里面
       	# 图片内容写入文件
      f.write(img_resp.content)  # img_resp.content是字节
      time.sleep(1)

​ 为了了解进度,可以加入提示语

#如:
	print('done')

​ 防止ip被封

import time

#在for循环中:
	time.sleep(1)

mode='rb'

image-20210719000415110

done!

image-20210719002303997

8.完整代码

import requests
from bs4 import BeautifulSoup
import time

url = "https://umei.net/katongdongman/"
resp = requests.get(url)

resp.encoding = resp.apparent_encoding
mainpage = BeautifulSoup(resp.text, "html.parser")

# 在主页面找到分区

ChildPages = mainpage.find("div", attrs={"class": "TypeList"})
# print(ChildPages)
childs = ChildPages.find_all("a")
for child in childs:
    # 从BeautifulSoup对象拿到里面的href属性的值,直接用get
    # print(child.get("href"))

    child_page_resp = requests.get("https://umei.net/"+child.get("href"))
    child_page_resp.encoding = 'utf-8'
    child_page_text = child_page_resp.text

    child_page = BeautifulSoup(child_page_text, "html.parser")
    p = child_page.find("p", align="center")
    img = p.find("img")
    src = img.get("src")

    # 下载图片
    img_resp = requests.get(src)
    img_name = src.split("/")[-1]
    # 拿到url中的最后一个/后面的内容
    with open("picture/"+img_name, mode="wb")as f:  # 放在提前建好的picture文件夹里面
       # 图片内容写入文件
        f.write(img_resp.content)  # img_resp.content是字节
        time.sleep(1)
    print('done',img_name)

print('all done!')

resp.close()

四.遇到的问题

1.writerow

image-20210718001108562

一开始csvwriter.writerow([name,lowest,mean,highest,guige,unit,date])写成了csvwriter.writerow(name,lowest,mean,highest,guige,unit,date)

以上是关于python爬虫入门的主要内容,如果未能解决你的问题,请参考以下文章

python爬虫入门

如何入门 Python 爬虫?

python网络爬虫入门

python爬虫入门

如何入门 Python 爬虫

python爬虫如何入门