scrapy+selenium爬取需要登录需要验证码的网站

scrapy+selenium爬取需要登录需要验证码的网站

站在巨人的肩膀上
采取了大神的思路,加上自己项目的需求

点击打开大神文章连接

本文只是将结果打印了出来,没有保存过程,后续会继续写文章

思路注释上都有,就不墨迹了

import json
import time
import urllib
import urllib.request
from pathlib import Path

import scrapy
from scrapy.http import Request,FormRequest
from selenium import webdriver
from selenium.webdriver.chrome.options import Options


class DbSpider(scrapy.Spider):
    name = 'long'
    allowed_domains = ['dc.oilchem.net']
    # 模拟请求的headers,非常重要,不设置也可能网站不让你访问
    headers = {
        'Host': 'dc.oilchem.net',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.104 Safari/537.36',
    }


    # start_urls = ['http://douban.com/']

    # scrapy请求的开始时start_request
    def start_requests(self):
        longzhong_findUrl='https://dc.oilchem.net/price_search/list.htm?businessType=2&varietiesName=PP%E7%B2%92&varietiesId=319&templateType=6&flagAndTemplate=3-4;2-7;6-null;1-6;6-null&channelId=1775&oneName=%E5%A1%91%E6%96%99&twoName=%E9%80%9A%E7%94%A8%E5%A1%91%E6%96%99'
        if not Path('longzhongCookies.json').exists():
            __class__.loginlongzhong()
            # 先执行login,保存cookies之后便可以免登陆操作

        #毕竟每次执行都要登陆还是挺麻烦的,我们要充分利用cookies的作用
        #从文件中获取保存的cookies
        with open('longzhongCookies.json','r',encoding='utf8') as f:
            listcookies=json.loads(f.read()) # 获取cookies

        #把获取的cookies处理成dict类型
        cookies_dict=dict()
        for cookie in listcookies:
            # 在保存成dict时,我们其实只要cookies中name和value,而domain等其他都可以不要
            cookies_dict[cookie['name']]=cookie['value']

        # scrapy发起其他页面请求时,带上cookies=cookies_dict即可,同时记得带上header值,
        yield scrapy.Request(url=longzhong_findUrl,cookies=cookies_dict,callback=self.parse,headers=__class__.headers)



    #使用selenium登陆隆重并获取登陆后的cookies,后续需要登录的操作都可以利用cookies
    @staticmethod
    def loginlongzhong():
        #登录网址
        loginurl='https://www.oilchem.net'
        #加载webdriver驱动,用于获取登陆页面标签属性
        driver=webdriver.Chrome()
        #加载页面
        driver.get(loginurl)

        time.sleep(3) #执行休眠3s等待浏览器的加载

        # 方式1:通过填充用户名和密码
        # 获取隐藏的登陆页面
        try:
            driver.find_element_by_partial_link_text(u"登录").click()
            print("测试通过,partial_link_text定位成功")
        except Exception as e:
            print("测试失败,未定位到partial_link_text", format(e))
        # 获取用户名框
        driver.find_element_by_name('username').clear()
        # 填充用户名
        driver.find_element_by_name('username').send_keys(u'15021328563')
        # 获取密码框
        driver.find_element_by_name('password').clear()
        # 填充密码
        driver.find_element_by_name('password').send_keys(u'15021328563')
        input('检查网页是否有验证码要输入,有就在网页输入验证码,输入完,控制台按回车;如果无验证码,则直接回车:')
        # 点击登录按钮,有时候网页会在输入密码后弹出验证码,这一步之后人工校验
        # < button type = "button" onclick = "dialogLogin()" > 登录 < / button >
        # <div class="form-sub"><button type="button" οnclick="dialogLogin()">登录</button></div>
        driver.find_element_by_class_name("form-sub").click()

        # # 方式2 直接通过扫描二维码,如果不是要求全自动化,建议用这个,非常直接,毕竟我们这一步只是想保存登录后的cookies,至于用何种方式登录,可以不必过于计较
        # driver.find_element_by_css_selector(
        #     "button[class='Button Button--plain']").click()
        # input("请扫描页面二维码,并确认登录后,点击回车:")  # 点击二维码手机扫描登录

        time.sleep(3) #同样休眠3s等待登录完成
        input("检查网页是否有完成登录跳转,如果完成则直接回车:")

        # 通过上述的方式实现登录后,其实我们的cookies在浏览器中已经有了,我们要做的就是获取
        # selenium为我们提供了get_cookies来获取登陆cookies的作用
        cookies=driver.get_cookies()
        driver.close() #获取cookies便可以关闭浏览器
        # 然后关键就是保存cookies,之后请求从文件中读取cookies就可以省去每次都要登录一次的
        # 当然可以吧cookies返回回去。但是之后每次请求都要先执行一次login没有发挥cookies的作用
        jsonCookies=json.dumps(cookies) #通过json将cookies写入文件
        with open('longzhongCookies.json','w') as f:
            f.write(jsonCookies)
        print(cookies)



    def parse(self, response):
        diqu = response.xpath("//div[@class='containerList line-height22']/div[@class='container']/div")
        print('解析文本:-----------------')
        # print(diqu)
        for table in diqu:
            # table.xpath(...) 提取的一个列表,其中只有一个值   加上[0],取列表中的第一个
            title = table.xpath(".//div[@class='container-title']/div/span/text()")[0]
            # title是一个Selector选择器 用选择器.extract()提取其中的data数据
            # extract(): 这个方法返回的是一个数组list,,里面包含了多个string,如果只有一个string,则返回['ABC']
            # 这样的形式。
            # extract_first():这个方法返回的是一个string字符串,是list数组里面的第一个字符串。
            print(title.extract())
            # print(table)
            # table.xpath(...) 提取的一个列表,其中只有一个值   加上[0],取列表中的第一个
            tableShow = table.xpath(".//div[@class='tabCar']/div[@class='tableList shows']")[0]
            # print(tableShow)

            table_header = tableShow.xpath(".//table//tr/th/text()").extract()
            td1_product_list = tableShow.xpath(".//table//tr/td[1]/a/text()").extract()
            td2_SPEC_list = tableShow.xpath(".//table//tr/td[2]/text()").extract()
            td3_norm_list = tableShow.xpath(".//table//tr/td[3]/text()").extract()

            # <td>销售公司名</td><td></td>
            # 这个字段存在<td></td>这样的形式,如果还用/text()的形式,只能提取到['销售公司名'],如果用.xpath('string(.)')可以提取到['销售公司名','']
            # 好处是 长度一致。   具体问题具体分析嘛
            td4_sellcompany_html = tableShow.xpath(".//table//tr/td[4]")
            td4_sellcompany_list = []
            for i in td4_sellcompany_html:
                td4_sellcompany_list.append(i.xpath('string(.)').extract_first())

            td5_productcompany_list = tableShow.xpath(".//table//tr/td[5]/text()").extract()
            td10_price_list = tableShow.xpath(".//table//tr/td[10]/@price").extract()

            # print(td_list)
            print('{}有:{}条数据'.format(title.extract(), len(td10_price_list)))

            t_header = [table_header[0], table_header[1], table_header[2],
                        table_header[3], table_header[4], table_header[9]]
            print(t_header)
            for t1, t2, t3, t4, t5, t10 in zip(td1_product_list, td2_SPEC_list, td3_norm_list,
                                                    td4_sellcompany_list, td5_productcompany_list, td10_price_list):
                list_per = [t1, t2, t3, t4, t5, t10]
                print(list_per)
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Scrapy框架和Selenium模拟登陆微博是一种常见的爬取微博评论的方法。通过Scrapy框架可以方便地发送HTTP请求和解析响应数据,而Selenium则可以模拟用户登录微博。 然而,微博对于爬虫的反爬措施比较严格,因此在爬取过程中可能会遇到一些问题。微博会自动跳转到评论比较少的页面,导致爬取的评论数量不多。此外,微博还会检测到爬虫程序并采取一些措施来防止爬取。 为了应对网站的反爬策略,可以采取以下措施: 1. 使用代理IP:通过使用代理IP可以隐藏真实的请求来源,增加爬虫的隐匿性。 2. 随机延时:在发送请求之前,可以引入随机延时,模拟人类的操作习惯,以避免被检测为爬虫。 3. 设置请求头:设置合理的请求头信息,包括User-Agent、Referer等,使请求看起来更像是正常的浏览器请求。 4. 使用验证码识别:如果网站验证码机制,可以使用验证码识别技术自动处理验证码。 5. 使用分布式爬虫:通过使用分布式爬虫,可以通过多个节点来爬取数据,减少单个节点的访问频率,降低被封禁的风险。 综上所述,使用Scrapy框架和Selenium模拟登陆微博可以实现爬取微博评论的功能,但同时也需要应对微博的反爬措施,采取相应的策略来提高爬取的成功率。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [python爬虫——scrapy+selenium爬取新浪微博及评论](https://blog.csdn.net/csdn950212/article/details/86583624)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值