使用python写一个爬虫所遇到的问题汇总

1、请求头的伪装

1.1、 前言

  • 比较常见的反爬虫策略,就是验证请求头里的User-Agent内容和请求的IP地址。所以我们需要伪装我们的请求头和发起请求的IP地址。请求头的伪装我们可以使用fake-useragent库,随机的生成User-Agent

1.2、实际使用中:我们可能还是会遇到2个问题。

  • 第一个:User-Agent 调用太过频繁报错
  • 第二个:目标网站反爬虫策略不仅仅验证了,我上面所说的东西。
  • 针对以上2个问题最简单的方式,就是捕获此异常。然后调用 time.sleep(2),让程序休眠一段时间。再继续任务。

1.3、常见的异常

  • 当你看到你的程序抛出了抛出ConnectionError错误,那一般就是因为目标网站监测出你是爬虫了。

2、内容解析find_all()使用说明(参考Beautiful Soup 4.9.0 文档)

find_all()
方法签名:find_all(name,attrs,recursive,string,limit,** kwargs)

该find_all()方法浏览标记的后代,并检索与过滤器匹配的所有后代。我在“种类的过滤器”中给出了几个示例,但这里还有更多示例:

soup.find_all("title")
# [The Dormouse's story]

soup.find_all("p", "title")
# [

The Dormouse's story

]
soup.find_all("a") # [Elsie, # Lacie, # Tillie] soup.find_all(id="link2") # [Lacie] import re soup.find(string=re.compile("sisters")) # 'Once upon a time there were three little sisters; and their names were\n' 其中一些应该看起来很熟悉,但另一些则是新的。为string或传递值是什么意思id?为什么 找到带有CSS类“ title”的<p>标签?让我们看看的参数。find_all("p", "title")find_all() 该name参数 传递一个值name,您将告诉Beautiful Soup仅考虑带有特定名称的标签。文本字符串以及名称不匹配的标签都将被忽略。 这是最简单的用法: soup.find_all("title") # [The Dormouse's story] 从各种过滤器中回想一下,to的值name可以是字符串,正则表达式,列表,函数或值True。 关键字参数 任何无法识别的参数将被转换为标签属性之一的过滤器。如果您为名为的参数传递值id,Beautiful Soup将根据每个标签的'id'属性进行过滤: soup.find_all(id='link2') # [Lacie] 如果您输入的值href,Beautiful Soup将根据每个标签的'href'属性进行过滤: soup.find_all(href=re.compile("elsie")) # [Elsie] 您可以基于字符串,正则表达式,列表,函数或值True过滤属性。 此代码查找其id属性具有值的所有标记,而不管该值是什么: soup.find_all(id=True) # [Elsie, # Lacie, # Tillie] 您可以通过传入多个关键字参数来一次过滤多个属性: soup.find_all(href=re.compile("elsie"), id='link1') # [Elsie] 某些属性(例如HTML 5中的data- *属性)具有不能用作关键字参数名称的名称: data_soup = BeautifulSoup('
foo!
'
, 'html.parser') data_soup.find_all(data-foo="value") # SyntaxError: keyword can't be an expression 您可以在搜索中使用这些属性,方法是将它们放入字典中并将该字典find_all()作为 attrs参数传递: data_soup.find_all(attrs={ "data-foo": "value"}) # [
foo!
]
您不能使用关键字参数来搜索HTML的“名称”元素,因为Beautiful Soup使用该name参数来包含标签本身的名称。相反,您可以在attrs参数中为'name'赋值 : name_soup = BeautifulSoup('', 'html.parser') name_soup.find_all(name="email") # [] name_soup.find_all(attrs={ "name": "email"}) # []

3、源码参考

3.1、获取代理(白嫖代理)

无忧代理-可白嫖3个小时
快代理-白嫖4小时

  • 我的demo里使用的是快代理,目标网站貌似反爬虫机制不是特强,所以我就没做请求头伪装。不过,抓下来的代理100个里面只有1-2个可以用。就算是做成了多线程,也是满得要死。
#!/usr/bin/env python  
# _*_ coding:utf-8 _*_  
#  
# @Version : 1.0  
# @Time    : 20120/10/24
# @Author  : wjt
# @File    : parsing_html
# @Description: 获取快代理IP 集合

from bs4 import BeautifulSoup
import requests
import re
import time


def get_html(url):
    """
    获取页面的html文件
    :param url: 待获取页面的链接
    :param open_proxy: 是否开启代理,默认为False
    :param ip_proxies: 若开启,代理地址
    :return:
    """
    try:
        pattern = re.compile(r'//(.*?)/')
        host_url = pattern.findall(url)[0]
        headers = {
     
            "Host": host_url,
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:60.0) Gecko/20100101 Firefox/60.0",
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
            "Accept-Encoding": "gzip, deflate",
            "Connection": "keep-alive",
        }
        res = requests.get(url, headers=headers, timeout=5)
        # res.encoding = res.apparent_encoding  # 自动确定html编码,由于这里可能导致乱码,先注释掉
        print("抓取代理IP Html页面获取成功 " + url)
        return res.text     # 只返回页面的源码
    except Exception as e:
        print("抓取代理IP Html页面获取失败 " + url)
        print(e)

def get_kuaidaili_free_ip(begin_page_number):
    """
    获取快代理的免费ip,一次只获取100个
    :param ip_proxies: 要使用的代理ip(这里是用代理ip去爬代理ip)
    :param save_path: 代理ip保存路径
    :param open_proxy: 是否开启代理,默认为False
    :return:
    """
    ip_list_sum = []    # 代理ip列表
    a = 1
    while a<=1:  # 获取页数
        #开始爬取
        r = get_html("https://www.kuaidaili.com/free/inha/" + str(begin_page_number+a) + "/")
        # print("-10"+"\\"+"n")
        if(r == "-10\n"):
            return print("爬取代理IP操作太频繁!")
        # 页面解析
        soup = BeautifulSoup(r, "html.parser")
        tags_ip = soup.tbody.find_all(attrs={
     "data-title": "IP"} )
        tags_port = soup.tbody.find_all(attrs={
     "data-title": "PORT"} )
        min_index =0
        max_index = len(tags_ip)-1
        while min_index<=max_index:
            ip_info = tags_ip[min_index].get_text()+":"+tags_port[min_index].get_text()
            ip_list_sum.append(ip_info)
            min_index+=1
        a+=1
    return ip_list_sum
    
# if __name__ == "__main__":
#    get_kuaidaili_free_ip(1)
    

3.2、爬取目标网站:根据百度关键词搜索

#!/usr/bin/env python  
# _*_ coding:utf-8 _*_  
#  
# @Version : 1.0  
# @Time    : 20120/10/24
# @Author  : wjt
# @File    : my_reptiles.py
# @Description: 爬取目标网站百度关键词搜索
import requests
from bs4 import BeautifulSoup
import re
import json
import time
import datetime
import threading  # 多线程
import os  # 文件操作
import parsing_html   #引入获取代理的类
from fake_useragent import UserAgent #爬虫请求头伪装

ip_list =[]  #代理IP集合
begin_page_number = 0  #代理IP源开始爬取页码

# 根据关键字搜索
def get_baidu_wd(my_wd,proxies_ip):
    # 构建查询条件
    my_params = {
     'wd': my_wd}
    
    proxies = {
     
        "http": "http://"+proxies_ip,   # http  型的
        "https": "http://"+proxies_ip   # https 型的
    }
    try:
        ua = UserAgent() #爬虫请求头伪装
        # 定制请求头
        my_headers = {
     
            "User-Agent":ua.random,
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            "Accept-Language": "zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
            "Accept-Encoding": "gzip, deflate",
            "Connection": "close",
        }  
        r = requests.get('https://www.baidu.com/s?ie=UTF-8',
                           params=my_params, headers=my_headers,proxies = proxies,timeout=2, verify=False)
    except (requests.exceptions.ConnectTimeout,requests.exceptions.ProxyError,Exception):
        print(proxies_ip+"超时!")
    else:
        if r.status_code == 200:
            print(proxies_ip+"成功!")
    finally:
        pass
    
    
#开始抓取任务的
def newmethod304():
    global ip_list
    global begin_page_number
    while 1==1:
        if len(ip_list) == 0:
            time.sleep(1)
            ip_list = parsing_html.get_kuaidaili_free_ip(begin_page_number)
        while len(ip_list) !=0:
            proxies_ip = ip_list.pop().replace('\n','') #移除列表中的一个元素(默认最后一个元素),并且返回该元素的值
            # 创建新线程
            myThread1(proxies_ip).start()    
        begin_page_number+=1   

#线程任务
class myThread1(threading.Thread):
    def __init__(self,proxies_ip):
        threading.Thread.__init__(self)
        self.proxies_ip = proxies_ip
    def run(self):
        print("开始线程:" + self.proxies_ip)
        get_baidu_wd('周杰伦',self.proxies_ip)  


if __name__ == '__main__':
    newmethod304()

    

4、参考

Requests官方参考文档
Beautiful Soup 4.9.0 文档,内容解析参考
fake-useragent参考

广告

如有定制爬虫需求请联系:[email protected]

你可能感兴趣的:(Python,1024程序员节,python,爬虫)