php抓取网页匹配url(三个流程获取网页的基础及获取方法(二十五))

优采云 发布时间: 2022-02-24 08:27

  php抓取网页匹配url(三个流程获取网页的基础及获取方法(二十五))

  获取网页的三个过程

  获取网页的基础知识:requests、urllib、selenium

  进阶:多线程、登录抓取、破禁IP、使用服务器抓取

  解析网页

  基础:re正则表达式、Beautiful、lxml

  进阶:解决中文乱码

  存储数据

  基础知识:保存到 txt 和 csv 文件

  高级:存储在 MySQL\MongoDB 数据库中

  或者直接使用 Scrapy 框架。

  写一个简单的爬虫

  import requests

import time

from bs4 import BeautifulSoup

link="http://www.santostang.com//"

headers={

'User-Agent':'Mozilla/5.0(Windows;U;Windows NT6.1;en-US;rv:1.9.1.6) Gecko/20091201 Firefox/3.5.7'}

r=requests.get(link,headers=headers)

print(r.text)

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

time.sleep(10)

title=soup.find("h1",class_="post-title").a.text

print(title)

with open('title_test.txt',"a+") as f:

f.write(title)

  学习使用浏览器菜单栏中的inspect菜单查看浏览器的html语句

  其中,requests.get 表示获取对应的对应内容。只有使用它只能读取网页的一些设置值,比如语言设置、响应状态值等等。

  自定义请求

  这部分主要是解决一些网页必须设置一些参数才能获取的问题。这部分的内容包括传递URL参数、自定义请求头、发送POST请求、设置超时等。

  传递 URL 参数

  将获取代码修改为以下带参数的请求

  key_dict={

'key1':'value1','key2':'value2'}

r=requests.get('http://httpbin.org/get',params=key_dict)

  它形成了我们需要的 URL 格式

  自定义请求标头

  这部分的内容需要浏览器-Network查看请求头的具体信息,请求头的内容可以交给requests.get函数的headers部分。

  发送 POST 请求

  与GET不同的是,get请求的参数后跟URL,当有重要密码等参数时,非常不安全。

  发送 POST 请求的规则如下:

  key_dict={

'key1':'value1','key2':'value2'}

r=requests.post('http://httpbin.org/get',data=key_dict)

  暂停

  限制访问网页的时间。

  只需在请求功能后添加

  超时=特定值

  爬豆瓣代码

  import requests

import time

from bs4 import BeautifulSoup

def get_movies():

headers={

'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0',

'Host':'movie.douban.com'}

movie_list=[]

for i in range(0,10):

link='http://movie.douban.com/top250?start='+str(i*25)

r=requests.get(link,headers=headers,timeout=10)

time.sleep(1)

#print(str(i+1),"页相应状态码",r.status_code)

soup=BeautifulSoup(r.text,"lxml")

div_list=soup.find_all('div',class_='hd')

for each in div_list:

movie=each.a.span.text.strip()

movie_list.append(movie)

return movie_list

movies=get_movies()

print(movies)

  动态网页抓取

  在学习之前,需要了解异步更新技术——AJAX。它的价值在于可以用少量代码异步更新网页,即网页的部分更新(内容改变,但url不变)。这样网页的爬取就比较复杂了,我们可以通过爬取网页的评论来了解动态网页爬取的过程。(通常在 JavaScript 中)

  一般使用

  浏览器审查

  先给出完整代码

  import json

import requests

link="https://api-zero.livere.com/v1/comments/list?callback=jQuery112405130785675025886_1620273279720&limit=10&repSeq=4272904&requestPath=%2Fv1%2Fcomments%2Flist&consumerSeq=1020&livereSeq=28583&smartloginSeq=5154&code=&_=1620273279722"

header={

'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:88.0) Gecko/20100101 Firefox/88.0'}

r=requests.get(link,headers=header)

json_string=r.text

json_string=json_string[json_string.find('{'):-2]

json_data=json.loads(json_string)

comment_list=json_data['results']['parents']

for eachone in comment_list:

message=eachone['content']

print(message)

  1.虽然网页源代码中没有出现数据,但是在网页查中还是可以找到想要的数据的,需要找到真正的评论文件才能爬取。

  2.获取数据后发现是乱码,所以需要用json解析。

  json_string[json_string.find('{'):-2]

  就是只提取字符串中符合json的部分,然后使用json.loads将字符串格式的响应体数据转换成json数据。使用它的结构,我们可以提取评论列表comment_list。

  通过 Selenium 模拟浏览器爬行

  主要解决了之前的方法找不到真正的源码的情况。可以模拟浏览器同时加载页面和抓取数据,使动态页面的获取变成静态的。

  1.打开对应驱动的页面,代码如下

  from selenium import webdriver

driver = webdriver.Firefox(executable_path=r'C:\Users\Gray\Desktop\geckodriver.exe')

driver.get("http://www.santostang.com/2018/07/04/hello-world/")

  这部分在jupyter中运行时可能会报错,因为当前版本的selenium没有geckodriver。下载后,运行上述程序(路径和地址必须正确)。运行后就可以打开对应的网页,模拟浏览器了。

  comment=driver.find_element_by_css_selector('div.reply-content')

content=comment.find_element_by_tag_name('p')

  这部分是通过CSS选择器获取class为reply-content,tag为p的文本。

  但是这部分的内容运行后还是有错误的。这是因为原代码中javascript的内容被解析成iframe框架,所以找不到div.reply-content。所以需要对框架进行解析

  driver.switch_to.frame(driver.find_element_by_css_selector("iframe[title='livere']"))

comment=driver.find_element_by_css_selector('div.reply-content')

content=comment.find_element_by_tag_name('p')

  Selenium 也可以模拟浏览器滑动点击,本文文章 仅供入门。

  高级操作(待补充)解析网页正则表达式

  正则表达式的内容写在我的另一篇文章文章中,这里主要写如何解析网页。

  

  重新匹配

  重新*敏*感*词*

  m=re.match('www','', flags=0)

  打印(m.span)

  打印(m.start)

  打印(m.end)

  您还可以将第一个参数替换为正则表达式。(匹配时一般采用贪心匹配的形式),匹配后通过group调用。group(0)为原字符串,1为左,1为右,不取任何内容。正则匹配中,一般字符串需要转义转义。

  研究

  re.match 只能从字符串的开头进行匹配,而 re.search 可以扫描整个字符串并返回第一个成功的匹配项。具体参数设置方法同re.match。

  重新查找

  它的优点是可以找到所有匹配的结果并显示在一个列表中,而前两个只能找到一个。

  re.findall('(.*?)',text),只提取括号内的内容。(后面学习html后也需要补充)

  美丽汤

  from bs4 import BeautifulSoup

  它是一个工具箱,提供标准库中的HTML解析器html.parser,以及一些第三方解析器如“lmxl”

  还有第三方解析器[“lmxl”、“xml”]、“html5lib”(最佳容错)等。

  方法

  import requests

from bs4 import BeautifulSoup

link="http://www.santostang.com//"

headers={

'User-Agent':'Mozilla/5.0(Windows;U;Windows NT6.1;en-US;rv:1.9.1.6) Gecko/20091201 Firefox/3.5.7'}

r=requests.get(link,headers=headers)

soup=BeautifulSoup(r.text,"lxml")

first_title=soup.find("元素名",class="具体class").a.text.strip()

  足够好

  soup.find_all("元素名称", class="特定类")

  返回一个列表。

  其他功能

  美化:soup.prettify()

  迭代文档的数量

  汤头.h1

  soup.header.div.contents #将其子节点输出到列表中

  soup.header.div.descendants #列出后代的节点

  .parent #列出父节点

  搜索文档树

  就是前面使用的 find\find_all

  CSS 选择器

  它既可以用作遍历树,也可以用作搜索。

  汤.select(“标题h1”)

  也可以遍历一个标签下的直接子标签

  soup.select("div>a") #即div下的所有a标签

  搜索时

  soup.select('a[href^=""]')#搜索开头

  使用 lxml 解析网页

  需要安装lxml库

  import requests

from lxml import etree

link="http://www.santostang.com//"

headers={

'User-Agent':'Mozilla/5.0(Windows;U;Windows NT6.1;en-US;rv:1.9.1.6) Gecko/20091201 Firefox/3.5.7'}

r=requests.get(link,headers=headers)

html=etree.HTML(r.text)

title_list=html.xpath('//h1[@class="post-title"]/a/text()')

print(title_list)

  "//h1" 表示全选

  子元素,后跟class选择class=post-title的元素,/a表示选择h1子元素的a元素,/text()表示提取a元素中的所有文本。

  找到XPATH的方法,用Chrome查看,在要提取的数据上右键,复制xPath。

  数据保存

  with open(r'',"a+") as f:

f.write()

f.close()

  import csv

with open('test.csv','r',encoding='UTF-8') as csvfile:

csv_reader=csv.reader(csvfile)

  import csv

output_list=["1","2"]

with open('test2.csv','a+',encoding="UTF-8",newline='') as csvfile:

w=csv.writer(csvfile)

w.writerow(output_list)

  import pymysql

#打开数据库连接

db=pymysql.connect("localhost","root","password","数据库名称")

cursor=db.cursor()

#sql插入

sql="""INSERT INT ..........

"""

try:

#sql语句执行

cursor.execute(sql)

#提交到数据库执行

db.commit()

#如果发生错误就回滚

except:

db.rollback()

db.close

  关于MongoDB的内容,后面需要用到和补充

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线