我的python学习笔记(requests_html、beautifulsoup、playwright)爬取电商平台热卖榜,解决动态加载,反爬等问题,适合初学者,浅显易懂

目录

前言

一、python基础知识

1.环境搭建

2.模块导入

 3.for循环

 4.try except的使用

 5.第三方库的使用

二、爬虫requests_html和beautiful soup使用

1.引入库

2.定义一个获取网页源码的get_code函数

3.定义一个解析网页源码的extract_infos函数

4.创建程序入口

5.完整代码

三、自动化测试框架playwright

1.结果展现

2.导入库

3.定义get_code(page_num)函数获取网页源码

4.对获取的源码进行解析

5.完整源码

总结


前言

本文是作者自学python的总结性文章,如有不严谨的地方,请各位不吝赐教,共同进步!


一、python基础知识

1.环境搭建

         选择anaconda+pycharm,原因是anaconda自带python,所以无需单独再安装python,并且anaconda里面已经自带了常用的第三方库,省去了额外下载第三方库的大量时间,python由于经常需要安装第三方库(可以用python写代码用到第三方库就跟平时喝水一样常见),所以采用anaconda+pycharm最适合。

        关于安装anaconda和pycharm网上很多教程,都挺简单的,这里就不讲了。

2.模块导入

        用python写代码,一般第一件事就是导入相关模块了,比如你想写个爬虫代码,需要导入模块,你想开发一个小程序,要先导入模块,你想写个代码对excel表格里的数据进行处理,也得先导入模块,总之,无论你用python做什么,都要先导入模块(所以用anaconda真的很方便,无需经常安装模块)

        导入的方法也很简单,一般常用2种,第一种就是import 这里是你要导入的模块名,第二种是from这里是你要导入的模块名 import 你要使用的类

        代码如下(示例):

#直接导入
import requests_html
#从bs4里只导入BeautifulSoup进行使用
from bs4 import BeautifulSoup

 3.for循环

        学会导入模块之后,接下来学习一些在python里常用的语法。

        for循环的使用也较为简单,主要用于我们要重复完成同一件事情的时候,就可以采用for循环,演示代码如下,我做了详细的备注:

z=0#首先定义z为0
a=list(range(0,20))#然后用range生成从0到19总共20个数字,并用list函数将其转为列表
for i in a:#用for循环遍历0到19,i即对应0到19那20个数字,每循环一次,就换下一个数字进行循环,直到最后一个数字19
    z+=i#每遍历一次z都加上i
print(z)#最后打印z,结果为190

 4.try except的使用

        这个一般是用来规避错误,让代码接着往下跑的,如果没有这个,当代码遇到bug时,就会报错,而有这个,当代码遇到bug时,则会去执行except后的代码。

 5.第三方库的使用

        用python完成不同任务时,需要使用不同的库

        爬虫应用:requests_html(和requests一样,但功能更丰富)、beautifulful soup

        数据分析:pandas、matplotlib

        开发应用程序:pyqt5

        自动化测试:playwright(和selenium同类型)

二、爬虫requests_html和beautiful soup使用

        这里以爬取国际电商平台为例子,这是那个国际电商平台

我的python学习笔记(requests_html、beautifulsoup、playwright)爬取电商平台热卖榜,解决动态加载,反爬等问题,适合初学者,浅显易懂_第1张图片

1.引入库

        第一步,导入要使用的requests_html和beautiful soup库,代码如下(示例):

"""第一步,导入爬虫应用库"""
from requests_html import HTMLSession,UserAgent
from bs4 import BeautifulSoup

2.定义一个获取网页源码的get_code函数

        第二步,我们定义一个获取网页源码的函数,主要用到上面导入进来的requests_html函数,在这一步,先创建一个session,后基于这个session发布网络请求get请求。

        接着是伪装浏览器,需要创建一个随机ua,即随机请求头,然后把伪装信息全部封装在headers字典里,作为后面发送get请求的一个参数。

        接下来是把发送请求得到的响应信息源码保存下来,并返回函数入口,供下面解析步骤使用

        代码如下(示例):

"""第二步,拿到网页源码,可以理解一次性拿到所有货物"""
def get_code(page):#定义一个函数,这个函数以页面为参数
    session=HTMLSession()#创建一个session,打地基,后续基于这个session进行爬取
    ua = UserAgent().random#创建一个随机请求头,相当于模拟浏览器的身份,不然别人知道你是爬虫软件,不把源码给你
    headers = {'user-agent': ua,
                   }#把伪装信息装在这个headers里,还有其他参数,在网页F12里可以找到很多,这里不过多伪装了
    url='https://www.amazon.com/Best-Sellers-Toys-Games-Board-Games/zgbs/toys-and-games/166225011/ref=zg_bs_pg_'+str(page)+'?_encoding=UTF8&pg='+str(page)#这是要爬取的网址
    response=session.get(url,headers=headers)#这里已经拿到了服务器的响应
    html=response.text#这里对提取响应里的源码
    return html

3.定义一个解析网页源码的extract_infos函数

        第三步,获取到网页源码之后,肯定就是要开始挑三拣四了,把我们想要的信息提取出来,这里我们以提取商品左上角的数字编号为例子。

我的python学习笔记(requests_html、beautifulsoup、playwright)爬取电商平台热卖榜,解决动态加载,反爬等问题,适合初学者,浅显易懂_第2张图片

         首先BeautifulSoup是一个类,使用前需要先实例化,完了之后创建一个numbers空列表用于存储编号。

        用contens方法拿到装有编号的一个个div标签,之后需要用for循环对这一个个div标签进行遍历,每一次都只提取我们想要的编号信息,标题、评分、价格我们都不要,只要左上角的标号。

        提取出来的标号一个个按顺序存放在事先准备好的numbers空列表里。

        最后把numbers打印出来,发现提取出来了,但是由于网站采取动态加载或者我们一开始伪装得不够好被识别出来了,我们只拿到前30个商品信息

我的python学习笔记(requests_html、beautifulsoup、playwright)爬取电商平台热卖榜,解决动态加载,反爬等问题,适合初学者,浅显易懂_第3张图片

         其实对于爬取不下来的网站,我一般会用playwright去爬,但是花费时间更多,下文会讲一下playwright的使用。

        代码如下(示例):

"""第三步,将网页源码拆解,提取我们想要的部分,可以理解为对货物进行分拣,只留下对我们有用的货物"""
def extract_infos(html):#定义提取信息函数
    soup = BeautifulSoup(html, 'lxml')#创建一个soup,解析信息基于此
    numbers=[]#创建一个空列表,待会用来装编号
    divs = soup.select_one('div[class="p13n-gridRow _cDEzb_grid-row_3Cywl"]').contents#找到装编号的标签
    for div in divs:#对每个装编号的标签进行提取编号,提取后将编号放进numbers里
        span=div.select_one('span[class="zg-bdg-text"]')
        number=span.text
        numbers.append(number)
    print(numbers)#遍历完后打印装满编号的numbers,一共抓取到前30个,网站反爬或者可能采用动态加载,需要其他技术

4.创建程序入口

        因为前面只是创建函数,所以必须创建函数入口来使用函数。

        关于这个步骤的作用,主要是因为python需要经常引用模块,有可能这里面的函数我在下一个代码里用到,到时候引用这个模块时,如果我创建了程序入口,那么就不会执行我引用模块的代码。

        总之,大家的代码都是这么写的,哈哈哈。我一开始也不理解,后来代码敲着敲着就懂了。

if __name__=='__main__':#程序入口
    for page in range(1,2):#只能抓取第一页的前30条,可能网站反爬技术太强了
        html=get_code(page)#使用get_code函数获取源码
        extract_infos(html)#提取信息

5.完整代码

        完整代码在这里,方便大家学习。

"""第一步,导入爬虫应用库"""
from requests_html import HTMLSession,UserAgent
from bs4 import BeautifulSoup

"""第二步,拿到网页源码,可以理解一次性拿到所有货物"""
def get_code(page):#定义一个函数,这个函数以页面为参数
    session=HTMLSession()#创建一个session,打地基,后续基于这个session进行爬取
    ua = UserAgent().random#创建一个随机请求头,相当于模拟浏览器的身份,不然别人知道你是爬虫软件,不把源码给你
    headers = {'user-agent': ua,
                   }#把伪装信息装在这个headers里,还有其他参数,在网页F12里可以找到很多,这里不过多伪装了
    url='https://www.amazon.com/Best-Sellers-Toys-Games-Board-Games/zgbs/toys-and-games/166225011/ref=zg_bs_pg_'+str(page)+'?_encoding=UTF8&pg='+str(page)#这是要爬取的网址
    response=session.get(url,headers=headers)#这里已经拿到了服务器的响应
    html=response.text#这里对提取响应里的源码
    return html

"""第三步,将网页源码拆解,提取我们想要的部分,可以理解为对货物进行分拣,只留下对我们有用的货物"""
def extract_infos(html):#定义提取信息函数
    soup = BeautifulSoup(html, 'lxml')#创建一个soup,解析信息基于此
    numbers=[]#创建一个空列表,待会用来装编号
    divs = soup.select_one('div[class="p13n-gridRow _cDEzb_grid-row_3Cywl"]').contents#找到装编号的标签
    for div in divs:#对每个装编号的标签进行提取编号,提取后将编号放进numbers里
        span=div.select_one('span[class="zg-bdg-text"]')
        number=span.text
        numbers.append(number)
    print(numbers)#遍历完后打印装满编号的numbers,一共抓取到前30个,网站反爬或者可能采用动态加载,需要其他技术

if __name__=='__main__':#程序入口
    for page in range(1,2):#只能抓取第一页的前30条,可能网站反爬技术太强了
        html=get_code(page)#使用get_code函数获取源码
        extract_infos(html)#提取信息

三、自动化测试框架playwright

1.结果展现

        上文用requests_html没能爬取下来的31-50号商品(动态加载的数据),采用playwright就能顺利采集下来,当然,代价就是爬取速度变慢,毕竟我们是完全模拟人为操作浏览器的,人操作浏览器肯定慢了,优点是更安全,基本不存在被反爬。

        在开始讲解playwright的使用之前,把playwright先简单介绍一下,它的功能类似selenium,但是更新潮,我上网搜过相关信息,大概的意思就是,playwright是微软开源的框架,更好用,是未来的趋势,功能更全面,并且支持代码录制(打开浏览器随便点一点,就能生成对应的代码,再根据代码改改就能直接用了,非常方便)

        下图是成功爬取31-50号商品的结果图。

2.导入库

        第一步仍然是先导入相关库,要使用playwright一般是用from playwright.sync_api import sync_playwright导入的,我们主要是用它来获取网页源码,解析部分仍然是交给BeautifulSoup来做,这次我们还额外导入了re模块,用正则表达式精准提取数字,正则表达式是一个非常有趣的语法,主要是用在字符串处理方面。

        代码如下(示例):

"""第一步,导入需要用到的库"""
from playwright.sync_api import sync_playwright#这个就是playwright中用到的
from bs4 import BeautifulSoup
import re#这是正则表达式,非常顶级的语法

3.定义get_code(page_num)函数获取网页源码

        第二步仍然是定义一个函数来获取网页源码,只不过这次与用requests_html不一样,我们用自动化测试框架playwright来获取,可以额外获取到动态加载部分的源码,即31-50号商品的信息。

        首先是用我们导入的sync_playwright生成一个browser,即浏览器,这里生成的是火狐浏览器,接着用生成的浏览器生成一个context,接着用生成的context生成一个page,即网页(就非常套娃,反正我们最后想要的就是这个page)。

        接着就可以用page去访问你任何想访问的网址了,用page.goto()即可。

        获取源码的函数主要是html = page.content(),用这个即可获得源码。

        为了让31-50号商品信息也加载出来,我们模仿浏览器滚动页面的操作,主要是用到这个方法

        for i in range(15):#前面说过31-50号商品是动态加载,我让网页自己滚动鼠标15次,让31-50号商品加载出来
            page.mouse.wheel(0,1000)  # 每次页面向下滚动1000个像素
            page.wait_for_timeout(500)#滚完一次都休息0.5秒,避免太快被反爬

         细心的朋友应该已经发现了为什么我要循环15次滚动页面了,原因是我在实操时发现,无论我滚动的像素值调得多么高,即使是10000个像素的滚,实际上仍然只滚了一点而已,所以不得已只能拆开成多次滚动页面,这样也能避免反爬。

        关于为什么要添加那个add_init_script,主要是告诉服务器我们的浏览器不是webdriver驱动的(虽然我们就是用webdricer驱动的),这样就能避免反爬。

        第二步的所有源码如下:

"""第二步,拿到网页源码,这次要拿到货真价实的全部货物"""
def get_code(page_num):#定义一个函数,这个函数以页面数为参数
    with sync_playwright() as p:#playwright的这个东西太长了,把它当作p
        browser = p.firefox.launch(headless=False)#从p里创建一个Firefox浏览器,后续基于这个浏览器采集信息
        context = browser.new_context()#创建一个背景,加入storage_state参数可以免登录,这里不需要登录就不加进来了
        page = context.new_page()#根据这个背景创建一个网页
        page.add_init_script(
            """
                Object.defineProperties(navigator, {
                    webdriver:{
                        get:()=>undefined
                    }
                });
            """
        )#这玩意可以避免被反爬,加上就完了
        url='https://www.amazon.com/Best-Sellers-Toys-Games-Board-Games/zgbs/toys-and-games/166225011/ref=zg_bs_pg_'+str(page_num)+'?_encoding=UTF8&pg='+str(page_num)#这是要爬取的网址
        page.goto(url)#开始进入网址
        #page.wait_for_load_state('networkidle')#这玩意用来顺利加载网页的,在其他地方很有用,很奇怪在这里没用
        for i in range(15):#前面说过31-50号商品是动态加载,我让网页自己滚动鼠标15次,让31-50号商品加载出来
            page.mouse.wheel(0,1000)  # 每次页面向下滚动1000个像素
            page.wait_for_timeout(500)#滚完一次都休息0.5秒,避免太快被反爬

        html = page.content()#拿到源码
        page.close()#关闭网页
        return html#把源码返回到函数入口

4.对获取的源码进行解析

        第三步仍然是进行解析,不过这次我们结合re模块对数字进行精准匹配,正则表达式的功能还是非常强大的。基本上和用requests_html爬虫的解析步骤差不多,源码如下:

def extract_infos(html):#定义提取信息函数,和前文几乎一样
    soup = BeautifulSoup(html, 'lxml')#创建一个soup,解析信息基于此
    numbers=[]#创建一个空列表,待会用来装编号
    divs = soup.select_one('div[class="p13n-gridRow _cDEzb_grid-row_3Cywl"]').contents#找到装编号的标签
    for div in divs:#对每个装编号的标签进行提取编号,提取后将编号放进numbers里
        span=div.select_one('span[class="zg-bdg-text"]')
        number=re.findall(r"\d+",str(span))#这里用正则表达式准确提取数字
        numbers.append(number)
    print(numbers)#遍历完后打印装满编号的numbers,这次全拿到了

     

5.完整源码

        程序入口还是要创建的,放在完整源码里了,如下:

"""第一步,导入需要用到的库"""
from playwright.sync_api import sync_playwright#这个就是playwright中用到的
from bs4 import BeautifulSoup
import re#这是正则表达式,非常顶级的语法

"""第二步,拿到网页源码,这次要拿到货真价实的全部货物"""
def get_code(page_num):#定义一个函数,这个函数以页面数为参数
    with sync_playwright() as p:#playwright的这个东西太长了,把它当作p
        browser = p.firefox.launch(headless=False)#从p里创建一个Firefox浏览器,后续基于这个浏览器采集信息
        context = browser.new_context()#创建一个背景,加入storage_state参数可以免登录,这里不需要登录就不加进来了
        page = context.new_page()#根据这个背景创建一个网页
        page.add_init_script(
            """
                Object.defineProperties(navigator, {
                    webdriver:{
                        get:()=>undefined
                    }
                });
            """
        )#这玩意可以避免被反爬,加上就完了
        url='https://www.amazon.com/Best-Sellers-Toys-Games-Board-Games/zgbs/toys-and-games/166225011/ref=zg_bs_pg_'+str(page_num)+'?_encoding=UTF8&pg='+str(page_num)#这是要爬取的网址
        page.goto(url)#开始进入网址
        #page.wait_for_load_state('networkidle')#这玩意用来顺利加载网页的,在其他地方很有用,很奇怪在这里没用
        for i in range(15):#前面说过31-50号商品是动态加载,我让网页自己滚动鼠标15次,让31-50号商品加载出来
            page.mouse.wheel(0,1000)  # 每次页面向下滚动1000个像素
            page.wait_for_timeout(500)#滚完一次都休息0.5秒,避免太快被反爬

        html = page.content()#拿到源码
        page.close()#关闭网页
        return html#把源码返回到函数入口

def extract_infos(html):#定义提取信息函数,和前文几乎一样
    soup = BeautifulSoup(html, 'lxml')#创建一个soup,解析信息基于此
    numbers=[]#创建一个空列表,待会用来装编号
    divs = soup.select_one('div[class="p13n-gridRow _cDEzb_grid-row_3Cywl"]').contents#找到装编号的标签
    for div in divs:#对每个装编号的标签进行提取编号,提取后将编号放进numbers里
        span=div.select_one('span[class="zg-bdg-text"]')
        number=re.findall(r"\d+",str(span))#这里用正则表达式准确提取数字
        numbers.append(number)
    print(numbers)#遍历完后打印装满编号的numbers,这次全拿到了

if __name__=='__main__':#程序入口
    for page_num in range(1,2):#只能抓取第一页的前30条,可能网站反爬技术太强了
        html=get_code(page_num)#使用get_code函数获取源码
        extract_infos(html)#提取信息

总结

        本文主要讲了爬虫方面的知识,希望对大家有所帮助,如果可以给个赞,我会很开心。

你可能感兴趣的:(python知识整理,python,beautifulsoup,爬虫,自动化,学习)