关于爬虫技术的探讨

写这篇文章,主要用于交流目的,将自己最近学到的技术进行一个大致的总结。仅此而已,欢迎评论交流。

声明:本人写博客纯粹是喜欢python,仅此而已。

好啦,废话就这么多,接下来是正文。

笔者留意爬虫很多时候啦,写的爬虫脚本也是有点数量,至于质量和代码的可阅读性可能需要下功夫改进,鉴于本人自学原因,所以代码追求的更多的是可行性,并没有严格的进行代码的函数包装以及类的使用。

说到爬虫,我看过崔才庆的相关书籍,确实真的不错,书中谈论很多实现数据爬取的方法,本片博客也是参照这本书来浅谈爬虫技术。

我觉得实现爬虫的话其实使用的库其实就那么几个吧(个人觉得好用),当然可以根据自己喜好来,其实如果可以达到目的即可,我一般的话爬取静态网页的话,一般使用的是requests库,涉及到动态网页,网页内容是被渲染过的,然而自己对效率的话追求不高的话,我觉得selenium挺不错的,只是需要安装谷歌驱动配合使用,其实这个我觉得是比较好用的,不需要什么解决编码的问题,如果用requests的话有些网站需要解决编码问题,不是所有的网站用utf-8解码就可以啦,这个之前困惑自己也是很久的。再说说移动端,移动端如手机的内容爬取,个人比较推荐的是appium这个库,这个库和selenium库的语法规则很相似。其实selenium和appium库都是自动化测试所用的库,不仅仅是爬虫能够用到,其实自动化测试啊,额一些脚本如(挂网课啊还是比较好的)。

好啦进入正题吧,下面就介绍requests库、selenium库和appium库,最近好像有一个比较万能的库叫playwright,听说挺好用的,若是觉得我说的太过于普通,可以试试这个库,可以自己看文档学。

首先先讲讲requests库

其实requests库爬取东西真的不难,就那个套路罢了,可以设置模板,每次直接调用就行。

import requests
from lxml import etree
url="你想要爬取的网站"
headers={"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
}#设置headers,用于反爬
res=requests.get(url=url,headers=headers)#这里可以使用自己的代理池,但是一般人用不到,这样已经可以啦,加代理可以网上搜,一般是自己IP被封了时候可能用到,我基本上没用,良民良民

res.encoding=res.apparent_encoding#这句话是进行编码转化,一般人写的是res.encoding=utf-8,但是有时候很烦,这句话可以说比较万能,一般不会出现错误,这也是我之前搜寻很久的编码问题解决方法,一般写这个就好了。
html=etree.HTML(res.text)#页面解析
li_list=html.xpath('')#定位爬取相关内容

其实requests使用一般需要自己会抓包技术,找到对应内容的真实网址,然后对HTML进行解析提取自己想要的信息,多看看相关的视频即可,最难的也是笔者认为要命的东西就是那个提取类容部分,就是正则的使用,这个真的很重要,爬东西容易,解析东西还是比较难的,不然爬取下来不过是乱码罢了。

下边直接给大家上个例子吧,仅供学习交流使用

-*- codeing = utf-8 -*-
@Time : 2021/4/1 19:42
@Author : 你猜
@File : 新闻热点整合版程序.py
@software: PyCharm

import requests
from lxml import etree
import os
if not os.path.exists('D:/新闻热点'):
    os.mkdir('D:/新闻热点')
if not os.path.exists('D:/新闻热点/热点网址'):
    os.mkdir('D:/新闻热点/热点网址')
if not os.path.exists('D:/新闻热点/数据分析包'):
    os.mkdir('D:/新闻热点/数据分析包')

url="http://www.ijiandao.com/hot/media"
headers={"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
}
res=requests.get(url=url,headers=headers)
res.encoding='utf-8'
html=etree.HTML(res.text)
li_list=html.xpath('//ul[@class="hot_new_list"]//li')
fp=open('D:/新闻热点/热点网址/知乎,抖音,微博新闻热点.doc','w',encoding='utf-8')
fp1=open('D:/新闻热点/知乎,抖音,微博新闻热点.txt','w',encoding='utf-8')
fp2=open('D:/新闻热点/数据分析包/知乎,抖音,微博新闻热点.xlsx','w',encoding='utf-8')
times=1
for li in li_list:
    while times>10:
        times=1
        fp.write(str("--------------"*10)+"\n"*4)
        fp1.write(str("--------------"*10)+"\n" * 4)
        fp2.write(str("--------------" * 10) + "\n" * 4)
    img_src=li.xpath('./span[2]/a/text()')
    img_href=li.xpath('./span[2]/a/@href')
    if len(img_src)>0 and len(img_href)>0:
        img_href='http://www.ijiandao.com'+img_href[0]
        fp.write(str(times)+"、"+"\n"+str(img_src[0])+'\n'+str(img_href[0])+'\n'*2)
        fp1.write(str(times) +"、"+ "\n"+str(img_src[0])+ '\n' * 2)
        fp2.write(str(times) + "、"+str(img_src[0]) + '\n' * 2)
        print(str(img_src[0])+"爬取完成!!!")
        times=times+1
url="https://s.weibo.com/top/summary"
headers={"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
}
res=requests.get(url=url,headers=headers)

res.encoding='utf-8'
html=etree.HTML(res.text)
li_list=html.xpath('//div[@class="data"]//tr')
fp=open('D:/新闻热点/热点网址/微博新闻热点(详细版).doc','w',encoding='utf-8')
fp1=open('D:/新闻热点/微博新闻热点(详细版).txt','w',encoding='utf-8')
fp2=open('D:/新闻热点/数据分析包/微博新闻热点(详细版).xlsx','w',encoding='utf-8')
times=1
for li in li_list:
    img_src=li.xpath('./td[2]/a/text()')
    img_href=li.xpath('./td[2]/a/@href')
    if len(img_src)>0 and len(img_href)>0:
        #fp.write(img_src+'\n')
        #print(img_src,type(img_src))
        img_href='https://s.weibo.com/top/summary'+img_href[0]
        fp.write(str(times) + "、" + "\n" + str(img_src[0]) + '\n' + str(img_href[0]) + '\n' * 2)
        fp1.write(str(times) + "、" + "\n" + str(img_src[0]) + '\n' * 2)
        fp2.write(str(times) + "、" + str(img_src[0]) + '\n' * 2)
        print(str(img_src[0])+"爬取完成!!!")
        if times == 10:
            fp.write(str("--------------" * 10) + "\n" * 4)
            fp1.write(str("--------------" * 10) + "\n" * 4)
        if times == 20:
            fp.write(str("--------------" * 10) + "\n" * 4)
            fp1.write(str("--------------" * 10) + "\n" * 4)
        if times == 30:
            fp.write(str("--------------" * 10) + "\n" * 4)
            fp1.write(str("--------------" * 10) + "\n" * 4)
        if times == 40:
            fp.write(str("--------------" * 10) + "\n" * 4)
            fp1.write(str("--------------" * 10) + "\n" * 4)
        if times == 50:
            fp.write(str("--------------" * 10) + "\n" * 4)
            fp1.write(str("--------------" * 10) + "\n" * 4)
        times=times+1
url="http://top.baidu.com/buzz?b=1"
headers={"user-agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36"
}
res=requests.get(url=url,headers=headers)
res.encoding='gb2312'
html=etree.HTML(res.text)
li_list=html.xpath('//table[@class="list-table"]//tr')
fp=open('D:/新闻热点/热点网址/百度新闻热点.doc','w',encoding='utf-8')
fp1=open('D:/新闻热点/百度新闻热点.txt','w',encoding='utf-8')
fp2=open('D:/新闻热点/数据分析包/百度新闻热点.xlsx','w',encoding='utf-8')
times=1
for li in li_list:
    img_src=li.xpath('./td[2]/a[@href_top]/text()')
    img_href=li.xpath('./td[2]/a/@href')
    if len(img_src)>0:
        fp.write(str(times) + "、" + "\n" + str(img_src[0]) + '\n' + str(img_href[0]) + '\n' * 2)
        fp1.write(str(times) + "、" + "\n" + str(img_src[0]) + '\n' * 2)
        fp2.write(str(times) + "、" + str(img_src[0]) + '\n' * 2)
        print(str(img_src[0])+"爬取完成!!!")
        if times == 10:
            fp.write(str("--------------" * 10) + "\n" * 4)
            fp1.write(str("--------------" * 10) + "\n" * 4)
            fp2.write(str("--------------" * 10) + "\n" * 4)
        if times == 20:
            fp.write(str("--------------" * 10) + "\n" * 4)
            fp1.write(str("--------------" * 10) + "\n" * 4)
            fp2.write(str("--------------" * 10) + "\n" * 4)
        if times == 30:
            fp.write(str("--------------" * 10) + "\n" * 4)
            fp1.write(str("--------------" * 10) + "\n" * 4)
            fp2.write(str("--------------" * 10) + "\n" * 4)
        if times == 40:
            fp.write(str("--------------" * 10) + "\n" * 4)
            fp1.write(str("--------------" * 10) + "\n" * 4)
            fp2.write(str("--------------" * 10) + "\n" * 4)
        if times == 50:
            fp.write(str("--------------" * 10) + "\n" * 4)
            fp1.write(str("--------------" * 10) + "\n" * 4)
            fp2.write(str("--------------" * 10) + "\n" * 4)
        times=times+1

这段代码是我之前为了练手而做的,所以年代比较久远,还是那句话,这段代码可能没有维护,所以可能有几个网站的运行不了,大家图个乐,看看思路就好,欢迎评论交流。

接下来就是selenium

selenium需要下载对应的一个驱动哈,具体操作网上找,很简单的不难,这里不赘述啦,直接上模板

from selenium import webdriver
from selenium.webdriver import ChromeOptions
import time
option = ChromeOptions()  # 实例化一个ChromeOptions对象
option.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36")
option.add_experimental_option('excludeSwitches', ['enable-automation'])  # 以键值对的形式加入参数
option.add_experimental_option('useAutomationExtension', False)
wd= webdriver.Chrome(executable_path='D:/chromedriver.exe', options=option)  # 在调用浏览器,驱动时传入option参数就能实现undefined,executable_path是对应驱动的位置,自己放哪写哪就好。options是一个反爬的一个措施,这个也是自己搜索的一个,目前效果还行吧
wd.get('')#爬取网址,

下面上案例,其实selenium爬虫就是模拟用户操作,对网页内容进行爬取,这样更加灵活,对于一些动态的渲染网页简直好用到不行,再也不用去一个一个点开包,一个一个查找相应的数据,最大的弊端就是爬取效率,此外一切都好,还有就是注意time.sleep.的使用,因为是模拟人工操作,所以对网页跳转的时间可能因网速,服务器响应等可能加载时间比较久容易报错,可以设置显性等待和隐性等待进行解决。

相关例子如下,本例子仅供参考学习交流。

from selenium import webdriver
import time
start_time=time.time()
fp = open('D:/青年大学习提醒/名单1.txt', 'w', encoding='utf-8')
fp.write('\n')
wd = webdriver.Chrome(executable_path='D:/Chromedriver.exe')
wd.get('https://jxtw.h5yunban.cn/jxtw-qndxx/admin/login.php')
wd.find_element_by_id('LAY-user-login-username').send_keys('')#模拟登录
time.sleep(1)
wd.find_element_by_id('LAY-user-login-password').send_keys('')#模拟登录
wd.find_element_by_xpath('//*[@id="LAY-user-login"]/div[1]/div[2]/div[3]/button').click()
time.sleep(2)
wd.implicitly_wait(10)
try:
    wd.find_element_by_xpath('//*[@id="LAY-system-side-menu"]//a').click()
    time.sleep(1)
except:
    wd.find_element_by_xpath('//*[@id="LAY-system-side-menu"]//a').click()
    time.sleep(1)
wd.implicitly_wait(10)#隐性等待
i_frame = wd.find_element_by_class_name('layadmin-iframe')#窗口跳转
wd.switch_to.frame(i_frame)
time.sleep(2)
wd.find_element_by_xpath('/html/body/div[1]/div/div/div/div[2]/div[1]/div[3]/div[1]//input').click()
wd.implicitly_wait(10)
wd.find_element_by_xpath('/html/body/div[1]/div/div/div/div[2]/div[1]/div[3]/div[1]//input').clear()
time.sleep(1)
wd.find_element_by_xpath('/html/body/div[1]/div/div/div/div[2]/div[1]/div[3]/div[1]/div/div/dl/dd[53]').click()
time.sleep(1)
wd.find_element_by_xpath('//a[1]').click()
time.sleep(1)
name_list = wd.find_elements_by_xpath('/html/body/div[1]/div/div/div/div[2]/div[2]/div/div[2]/table/tbody/tr/td[6]')
time.sleep(1)
for name in name_list:
    name_new = name.text
    fp.write(name_new + '\n')
time.sleep(1)

wd.find_element_by_xpath('//a[2]').click()
time.sleep(1)
name_list = wd.find_elements_by_xpath('/html/body/div[1]/div/div/div/div[2]/div[2]/div/div[2]/table/tbody/tr/td[6]')
time.sleep(1)
for name in name_list:
    name_new = name.text
    fp.write(name_new + '\n')

好累啊,快受不了啦,大家凑合看吧哈哈,selenium注意的是,一个是那个等待时间的设置,再一个就是那个窗口的跳转wd.switch_to.frame(i_frame),就这个,还有就是进去了一个窗口,要记得写跳出窗口的操作,网上一位老师说的很好,就是你进入一扇门,走之前要关上一扇门再离开。大概就这么多,重要的是自己要去花时间去实际操作,这样才能孰能生巧。

最后就是移动端的操作,这个需要下载安装的操作比较多,需要安装appium桌面端还有模拟器,我用的模拟器是夜神浏览器,缺点是有些app在上面装不了。大家可以自己看着来,这个一定要按照网上操作来,是需要设置环境变量的,耐心点就好了。

下面上例子

from appium import webdriver
from appium.webdriver.extensions.android.nativekey import AndroidKey
from appium.webdriver.common.touch_action import TouchAction
import time
desired_caps = {
        "platformName": "Android",
        "platformVersion": "7",
        "deviceName": "127.0.0.1:62001",
        "appPackage": "com.tencent.mobileqq",
        "appActivity": ".activity.SplashActivity",
        "noReset": True,
        'unicodeKeyboard': True# 使用自带输入法,输入中文时填True
    }
driver = webdriver.Remote('http://localhost:4723/wd/hub', desired_caps)
driver.implicitly_wait(5)

name=[]
with open('D:/班群.txt','r',encoding='utf-8') as fp:
    list=fp.readlines()
    for li in list:
        li.index('\n')
        name_1=li[0:li.index('\n')]
        name.append('@%s'%name_1)
def class_enter(name):
    el6 = driver.find_element_by_id("com.tencent.mobileqq:id/input")
    el6.send_keys(name)

def class_name():
    el1 = driver.find_element_by_accessibility_id("搜索")
    el1.click()
    el2 = driver.find_element_by_id("com.tencent.mobileqq:id/et_search_keyword")
    el2.send_keys('')
    driver.implicitly_wait(7)
    el3 = driver.find_element_by_xpath(
        "/hierarchy/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.LinearLayout/android.widget.FrameLayout/android.widget.FrameLayout/android.widget.RelativeLayout/android.widget.AbsListView/android.widget.LinearLayout[2]/android.widget.LinearLayout/android.widget.LinearLayout/android.widget.RelativeLayout/android.widget.RelativeLayout/android.widget.TextView[1]")
    el3.click()
    class_enter(name=('请下面同学抓紧时间完成青年大学习%s'%name[0:]))
    # driver.find_element_by_id('com.tencent.mobileqq:id/fun_btn')
class_name()

appium这个本身很复杂,我感觉一般用不着,反正现阶段我没有用到,这个运行需要同时打开python+appium桌面端+夜神浏览器,还是比较多的,大家酌情使用吧,先这样吧,欢迎指正。

以上内容均是我个人进行总结,也许没有考虑到读者感受的地方请多多保函,海涵海涵,如有不才之处欢迎指正。

Original: https://blog.csdn.net/mobing678/article/details/123454962
Author: #一只有梦想的咸鱼#
Title: 关于爬虫技术的探讨

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/697694/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球