python爬虫学习笔记

包的导入及使用

requests请求

requests.get/post(url,params,data,headers,timeout,verify,allow_redirects,cookies)
  • url:要下载的目标网页的URL
  • params:字典形式,设置URL后的参数,如:?id=123&name=turtle
  • data:字典或字符串,一般用于POST方式提交数据
  • headers:设置user_agent、refer等请求头
  • timeout:超时时间,单位s
  • verify:True/False,是否进行HTTPS证书验证,默认是,需要自己设置证书地址
  • allow_redirects:True/False是否让requests做重定向处理,默认是
  • cookies:附带本地cookies数据

接受 response 响应

r = requests.get/post(url)

//查看状态码,若200为成功
r.status_code
//可以查看当前编码,以及变更编码
//(requests会根据Headers推测编码,推测不到则设置为ISO-8859-1可能导致乱码)
r.ecoding
//查看返回的网页内容
r.text
//查看返回的HTTP的headers
r.headers
//查看实际访问的URL
r.url
//以字节方式返回内容,如用于下载图片
r.content
//服务端要写入本地的cookies数据
r.cookies

创建URL爬取管理器
url_manager.py文件

class UrlManager():
    """
    url管理器
    """

    # 初始化
    def __init__(self):
        # 创建为待爬取URL和已爬取URL集合
        self.new_urls = set()
        self.old_urls = set()

    # 添加待爬取URL
    def add_new_url(self, url):
        # 若URL不存在或为空则跳过
        if url is None or len(url) == 0:
            return
        # 若URL在待爬取URL及已爬取URL中则跳过
        if url in self.new_urls or url in self.old_urls:
            return
        # 否则将URL存入待爬取URL集合中
        self.new_urls.add(url)

    # 循环添加待爬取URL集合
    def add_new_urls(self, urls):
        # 若URL不存在或为空则跳过
        if urls is None or len(urls) == 0:
            return
        # 存在则for循环加入待爬取URL中
        for url in urls:
            self.add_new_url(url)

    # 获取正在爬取URL
    def get_url(self):
        # 若有待爬取URL
        if self.has_new_url():
            # 将URL从待爬取URL集合中移除
            url = self.new_urls.pop()
            # 将URL加入已爬取URL集合
            self.old_urls.add(url)
            # 返回爬取的URL
            return url
        # 若没有待爬取URL
        else:
            # 返回None
            return None

    # 判断是否有待爬取URL
    def has_new_url(self):
        # 判断是否有元素
        return len(self.new_urls) > 0


if __name__ == "__main__":
    url_manger = UrlManager()

    url_manger.add_new_url("url1")
    url_manger.add_new_urls(["url1", "url2"])
    print(url_manger.new_urls, url_manger.old_urls)
    print(url_manger.has_new_url())

    print("#"*30)
    new_url = url_manger.get_url()
    print(url_manger.new_urls, url_manger.old_urls)
    print(url_manger.has_new_url())

    print("#"*30)
    new_url = url_manger.get_url()
    print(url_manger.new_urls, url_manger.old_urls)
    print(url_manger.has_new_url())

Beautiful Soup 语法

创建BeautifulSoup对象

form bs4 import BeautifulSoup

# 根据HTML网页字符串创建BeautifulSoup对象
soup = BeautifulSoup(
                html_doc,              # HTML文档字符串
                'html.parser',         # HTML解析器
                from_encoding='utf8'  # HTML文档编码
                )

搜索节点( find_all,find )

方法:find_all(节点名称, 节点属性, 节点文本) # 返回查找到的所有
      find(节点名称, 节点属性, 节点文本)     # 返回查找到的第一个

# 查找所有标签为a的节点
soup.find_all('a')

# 查找所有标签为a,链接符合/view/123.html形式的节点
soup.find_all('a', href='/view/123.html')

# 查找所有标签为div,class为abc,文件为Python的节点
soup.find_all('div', class_='abc', string='Python')

访问节点信息

得到节点:<a href='1.html'>Python</a>

# 获取查找到到节点的标签名称
node.name        # 得到 a

# 获取查找到的a节点的herf属性
node['herf']     # 得到 1.html

# 获取查找到的a节点的链接文字
node.get_text()  # 得到 Python

例子:python/web_crawler/bs4_test/test.py

测试

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7VQa36Ji-1688998591007)(爬取网站文章实例.png)]

爬取博客中的所有文章

import requests
from bs4 import BeautifulSoup
import re
from web_crawler.utils import url_manager

# 待爬取的网站地址
root_url = "http://www.crazyant.net"

# 初始化URL管理器
urls = url_manager.UrlManager()
# 将待爬取的网站地址加入URL管理器
urls.add_new_url(root_url)

# 打开爬取后数据写入的文件
fout = open("craw_all_pages.txt", "w")
# 若存在待爬取URL
while urls.has_new_url():
    # 获取正在爬取的URL
    curr_url = urls.get_url()
    # 根据URL爬取数据,并设置时间为3秒
    r = requests.get(curr_url, timeout=3)
    # 若爬取返回代码为200,则报错并跳过该URL
    if r.status_code != 200:
        print("error,return status_code is not 200", curr_url)
        continue

    # 创建BeautifulSou
    soup = BeautifulSoup(r.text, "html.parser")
    # 获取title
    title = soup.title.string

    # 将爬取的URL和title写入文件
    fout.write("%s\t%s\n" % (curr_url, title))
    # 刷新文件缓存
    fout.flush()
    # 打印写入文件的内容及剩余待爬取URL条数
    print("success: %s, %s, %d" % (curr_url, title, len(urls.new_urls)))

    # 获取所有标签为a的数据
    links = soup.find_all("a")
    # 循环加入待爬取集合中
    for link in links:
        # 获取标签为a中href的值
        href = link.get("href")
        # 若为空,则跳过
        if href is None:
            continue
        # 设置匹配模式
        pattern = r'^http://www.crazyant.net/\d+.html$'
        # 若与设置的匹配模式匹配,则加入待爬取URL集合
        if re.match(pattern, href):
            urls.add_new_url(href)
# 关闭文件
fout.close()

爬取排名前250的电影

# 使用pandas将数据写出到Excel
import pandas as pd
# 使用requests爬取网页
import requests
# 使用BeautifulSoup实现数据解析
from bs4 import BeautifulSoup
import pprint
import openpyxl
import json

# 构建分页数字列表
page_indexes = range(0, 250, 25)
list(page_indexes)


def download_all_html():
    """
    下载所有列表页面的HTML
    :return:得到的所有HTML
    """
    # 创建HTML集合
    htmls = []
    # 获取爬取页面每页的数据
    for idx in page_indexes:
        url = f"https://movie.douban.com/top250?start={idx}&filter="
        print("craw html:", url)
        # 设置用户代理(反爬取机制需使用)
        headers = {
            'User-Agent': '复制请求头中信息'
        }
        # 爬取的URL及将用户代理加入请求头
        r = requests.get(url, headers=headers)
        if r.status_code != 200:
            print(r.status_code)
            raise Exception("error")
        # 将爬取到的HTML加入集合
        htmls.append(r.text)
    return htmls


# 获取所有待爬取待HTML文件
htmls = download_all_html()


def parse_single_html(html):
    """
    解析单个HTML,得到数据
    :param html: 解析的HTML页面
    :return:
    """
    soup = BeautifulSoup(html, 'html.parser')
    # 获取所有项目
    article_items = (
        soup.find("div", class_="article")
        .find("ol", class_="grid_view")
        .find_all("div", class_="item")
    )
    datas = []
    # 循环从单个项目中获取数据
    for article_item in article_items:
        rank = article_item.find("div", class_="pic").find("em").get_text()
        info = article_item.find("div", class_="info")
        title = info.find("div", class_="hd").find("span", class_="title").get_text()
        stars = (
            info.find("div", class_="bd")
            .find("div", class_="star")
            .find_all("span")
        )
        rating_star = stars[0]["class"][0]
        rating_num = stars[1].get_text()
        comments = stars[3].get_text()

        # 添加获取的数据
        datas.append({
            "rank": rank,
            "title": title,
            "rating_star": rating_star.replace("rating", "").replace("-t", ""),
            "rating_num": rating_num,
            "comment": comments.replace("人评价", "")
        })
    # 返回获取的所有数据
    return datas


# 爬取单个网页中的数据
# pprint.pprint(parse_single_html(htmls[0]))

# 爬取全部网页中的数据
all_datas = []
for html in htmls:
    all_datas.extend(parse_single_html(html))
# 打印全部数据
# print(all_datas)
# 打印数据条数
# print(len(all_datas))

# 将获取的数据写入excel文件中
df = pd.DataFrame(all_datas)
df.to_excel("film_crawler.xlsx")

爬取广州10年天气数据

# headers中设置user agent翻爬机制
# 通过network抓包,分析ajax的请求和参数
# 通过for循环请求不同的参数数据
# 利用pandas实现excel的合并与保存

import requests
import pandas as pd

# 爬取url
url = "http://tianqi.2345.com/Pc/GetHistory"

# 设置请求头,绕开反爬机制
headers = {
    "User-Agent": """复制请求头中信息"""
}


def craw_table(year, month):
    """
    根据对应的年份和月份爬取对应的表格数据
    :param year: 爬取的年份
    :param month: 爬取的月份
    :return: 爬取的表格数据
    """
    # 爬取数据请求头中所携带参数
    params = {
        "areaInfo[areaId]": 59287,
        "areaInfo[areaType]": 2,
        "date[year]": year,
        "date[month]": month
    }
    resp = requests.get(url, headers=headers, params=params)

    if resp.status_code != 200:
        pass
    else:
        # 返回数据为json类型,提取data部分数据
        data = resp.json()["data"]
        # 获取天气数据
        df = pd.read_html(data)[0]
        return df


# 设空list存储天气数据
df_list = []
# 检索2012-2022年数据
for year in range(2012, 2023):
    # 检索每年中各月份数据
    for month in range(1, 13):
        print("爬取:", year, month)
        # 将爬取的数据放入df
        df = craw_table(year, month)
        # 将df加入list
        df_list.append(df)

# print(df_list)
# 将爬取到的数据合并,并写入excel表格中
pd.concat(df_list).to_excel("GuangZhouTemperature_10year.xlsx", index=False)

爬取全本小说

import requests
from bs4 import BeautifulSoup
import time

# 爬取的url
root_url = "https://www.kunnu.com/santi/"
# 设置请求头,绕开反爬机制
headers = {
    "": "复制请求头中信息"
}


def get_novel_chapters():
    """
    爬取小说每章的链接
    :return: 每章的链接+章节名
    """
    r = requests.get(root_url, headers=headers)
    if r.status_code != 200:
        print(r.status_code)
        return
    soup = BeautifulSoup(r.text, "html.parser")
    # 爬取 class=chapter 的 div 模块数据
    chapter = soup.find("div", class_="book-list clearfix")
    # print(chapter)

    # 设置空 list 存储章节链接和章节名
    data = []
    # 爬取 class=chapter 的 div 中的 li 中数据
    for li in chapter.find_all("li"):
        # li 中超链接设为 link
        link = li.find("a")
        # 若link为空,则跳过
        if not link:
            continue

        # print(link["href"])
        # 将爬取到的超链接补充完整,并与内容一起存入 data 中
        # data.append(("https://www.xiaoshuowanben.com%s" % link["href"], link.get_text()))
        data.append((link["href"], link.get_text()))
        # time.sleep(0.5)
    # 返回 data 列表
    return data


def get_chapter_content(url):
    """
    爬取每章节的内容
    :param url: 爬取的章节url
    :return: 章节内容
    """
    r = requests.get(url, headers=headers)
    soup = BeautifulSoup(r.text, "html.parser")
    return soup.find("div", id="nr1").get_text()


# 将获取的章节循环爬取
for chapter in get_novel_chapters():
    # 将 chapter 分为 url+title
    url, title = chapter
    print(url, title)
    # 将爬取的内容写入文件中,a 为找到文件后在文件后中加入,w 为找到文件后删除文件内容重写内容
    with open("三体1.txt", "a") as f:
        # 写入内容
        f.write(title + '\n')
        f.write(get_chapter_content(url))

修改

import requests
from bs4 import BeautifulSoup
import time

# 爬取的url
root_url = "https://www.kunnu.com/santi/"
# 设置请求头,绕开反爬机制
headers = {
    "User-Agent": "复制请求头中信息"
}


def get_novel_chapters():
    """
    爬取小说每章的链接
    :return: 每章的链接+章节名
    """
    r = requests.get(root_url, headers=headers)
    if r.status_code != 200:
        print(r.status_code)
        return
    soup = BeautifulSoup(r.text, "html.parser")
    # 爬取 class=chapter 的 div 模块数据
    book = soup.find_all("div", class_="book-list clearfix")

    # 设置空 list 存储章节链接和章节名
    data = []
    for chapter in book:
        # 爬取 class=chapter 的 div 中的 li 中数据
        for li in chapter.find_all("li"):
            # li 中超链接设为 link
            link = li.find("a")
            # 若link为空,则跳过
            if not link:
                continue

            # 将爬取到的超链接补充完整,并与内容一起存入 data 中
            # data.append(("https://www.xiaoshuowanben.com%s" % link["href"], link.get_text()))
            data.append((link["href"], link.get_text()))
            # time.sleep(0.5)
    # 返回 data 列表
    return data


def get_chapter_content(url):
    """
    爬取每章节的内容
    :param url: 爬取的章节url
    :return: 章节内容
    """
    r = requests.get(url, headers=headers)
    soup = BeautifulSoup(r.text, "html.parser")
    temp = soup.find("div", id="nr1")
    if temp is not None:
        text = temp.get_text()
        return text
    return


# 将获取的章节循环爬取
for chapter in get_novel_chapters():
    # 将 chapter 分为 url+title
    url, title = chapter
    print(url, title)
    # 将爬取的内容写入文件中,a 为找到文件后在文件后中加入,w 为找到文件后删除文件内容重写内容
    if chapter is not None:
        with open("三体完结.txt", "a") as f:
            # 写入内容
            f.write(title + '\n\n')
            f.write(get_chapter_content(url))
            f.write('\n')

改进爬取过程

# 只需要打开一次文件,即可进行写入操作
with open("三体完结.txt", "w") as f:
    # 将获取的章节循环爬取
    for chapter in get_novel_chapters():
        # 将 chapter 分为 url+title
        url, title = chapter
        print(url, title)
        # 将爬取的内容写入文件中,a 为找到文件后在文件后中加入,w 为找到文件后删除文件内容重写内容
        if chapter is not None:
            # 写入内容
            f.write(title + '\n\n')
            f.write(get_chapter_content(url))
            f.write('\n')

爬取图片

import requests
from bs4 import BeautifulSoup
import os

# 爬取网站url
url = "https://pic.netbian.com/e/search/result/?searchid=343"

resp = requests.get(url)
# 设置编码类型为 gbk
resp.encoding = 'gbk'

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

# 找到 class=clearfix 的 ul
ul = soup.find("ul", class_="clearfix")
# 检索 ul 中的所有图片
for img in ul.find_all("img"):
    # 将检索到的路径拼接,形成新的url
    src = f"https://pic.netbian.com{img['src']}"

    # 将 src 的最后一个字符串作为下载的图片名
    filename = os.path.basename(src)
    # 将图片写入 cat_photo 文件下,w 为写入,b 为以二进制形式进行写入操作
    with open(f"cat_photo/{filename}", "wb") as f:
        # 爬取图片url的数据
        resp_img = requests.get(src)
        # 将数据写入
        f.write(resp_img.content)
        

封装

import requests
from bs4 import BeautifulSoup
import os

# 爬取网站url
url = "https://pic.netbian.com/e/search/result/?searchid=343"


def craw_html(url):
    resp = requests.get(url)
    # 设置编码类型为 gbk
    resp.encoding = 'gbk'
    html = resp.text
    return html


def parse_and_download(html):
    soup = BeautifulSoup(html, "html.parser")

    # 找到 class=clearfix 的 ul
    ul = soup.find("ul", class_="clearfix")
    # 检索 ul 中的所有图片
    for img in ul.find_all("img"):
        # 将检索到的路径拼接,形成新的url
        src = f"https://pic.netbian.com{img['src']}"

        # 将 src 的最后一个字符串作为下载的图片名
        filename = os.path.basename(src)
        # 将图片写入 cat_photo 文件下,w 为写入,b 为以二进制形式进行写入操作
        with open(f"cat_photo/{filename}", "wb") as f:
            # 爬取图片url的数据
            resp_img = requests.get(src)
            # 将数据写入
            f.write(resp_img.content)


html = craw_html(url)
parse_and_download(html)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值